shopt -s extglob не работает должным образом

editphpini() subl /usr/local/etc/php/${1[1]}.${1[2,-1]}/php.ini

${1[1]}.${1[2,-1]} - это один из многих способов преобразования xyz в x.yz. Другими подходами могут быть: ${1[1]}.${1#?}, или ${1/(#m)?/$MATCH.}, или ${(j:.:)${(s::)1}} (для x.y.z)

.
3
12.07.2016, 01:43
2 ответа

Во-первых, extglob управляет тем, что ls видит в своей командной строке. Он не контролирует то, что ls делает с тем, что он видит в командной строке. Это важно, потому что опция -R для ls указывает ls рекурсивно исследовать любые каталоги, которые он видит в командной строке. Таким образом, даже если каталоги * uploads * явно не указаны в командной строке, ls найдет их, когда исследует их родительские каталоги.

Во-вторых, как вы знаете, не разбирает ls . Вывод ls не предназначен для использования в конвейерах или скриптах. Попытки использовать это в конечном итоге приводят к несчастью.

В-третьих, чтобы получить нужные файлы, попробуйте:

find ./public_html ! -path '*uploads*'

Чтобы объяснить:

  • ./ public_html сообщает find начать поиск в ./ public_html каталог.

  • Сама по себе опция -path '* uploads *' соответствует любому пути, содержащему шаблон * uploads * . ( -path аналогичен параметру find -name , но путь включает имена каталогов.) Предыдущий ! , однако, указывает на отрицание. Итак, вариант ! -path '* uploads *' исключает любое соответствие пути * uploads * .

Чтобы получить вывод в стиле ls при использовании функций find , рассмотрите:

find ./public_html ! -path '*uploads*' -exec ls -dalh {} +
7
27.01.2020, 21:11

John1024 добавил хорошее решение вашей очевидной проблемы, но, судя по комментариям, вы хотели бы лучше понять extglob. Я подозреваю, что одно из основных недоразумений могло заключаться в том, что extglobs будут работать рекурсивно - что высказывание ./ public_html /! (* Uploads *) исключает что-то с именем ./ public_html / wp-content / uploads / . Globs (расширение имени файла) одновременно работает только на уровне одного каталога. Похоронен в руководстве по bash в разделе Расширение имени файла :

При сопоставлении имени файла символ косой черты всегда должен совпадать явно.

Итак, как сказал Джон1024, команда ls не имела никаких (расширенных) параметров, которые имели бы форму ./ public_html / * uploads * , но она могла имели такой параметр, как ./ public_html / wp-content (который не соответствует исключенному шаблону), который затем было сказано -R для рекурсивного перечисления.

Чтобы исключить каталоги * uploads * с помощью extglobs в командной строке, вам нужно будет создать команду с таким количеством исключений, сколько имеется подкаталогов:

ls -dalh ./public_html/!(*uploads*) \
         ./public_html/!(*uploads*)/!(*uploads*) \
         ./public_html/!(*uploads*)/!(*uploads*)/!(*uploads*)
# ... etc ...

... также будьте осторожны, чтобы не использовать флаг ls -R . Тот же риск -R будет применяться к команде chmod. Потенциальный риск здесь состоит в том, что если в каком-либо подкаталоге «слишком много» файлов, вы рискуете заполнить список аргументов для ls . Этот подход хрупок, поскольку он не будет обнаруживать вновь созданные каталоги, глубина которых превышает количество написанных вами шаблонов, и сломает ( ls будет жаловаться на отсутствие каталога), если вы когда-нибудь имело на меньше подкаталогов , чем количество заданных шаблонов, что является длинным объяснением того, почему find является правильным инструментом для этой работы.

1
27.01.2020, 21:11

Теги

Похожие вопросы