Вопрос или проблема
Предположим, у меня есть эти файлы:
foo/bar/baz/test.js
foo/bar/baz/test.min.js
Если я выполню:
shopt -s globstar
shopt -s extglob
echo foo/bar/**/*!(.min).js
…это все равно будет соответствовать файлу test.min.js
.
Как мне его игнорировать?
В extglob, !(.min)
может соответствовать всему, кроме .min
(и всего, что содержит /
); это включает пустую строку!
Когда вы проверяете foo/bar/baz/test.min.js
с помощью глоба foo/bar/**/*!(.min).js
, вы получаете совпадение, потому что:
foo/bar/
соответствуетfoo/bar/
**/
соответствуетbar/
*
соответствуетtest.min
!(.min)
соответствует пустой строке.js
соответствует.js
То значение, которое вы хотите получить от !(.min)
, – это на самом деле “все, что не заканчивается на .min
“, что является отрицанием *.min
, поэтому используйте !(*.min)
, чтобы исправить проблему:
foo/bar/**/!(*.min).js
Ответ или решение
Использование Bash extglob с игнорированием паттернов: Подробное руководство
При работе с Bash и его механизмами сопоставления шаблонов, такими как globbing и extglob, возникают ситуации, когда необходимо исключить определённые файлы из результатов поиска. Один из наиболее распространённых случаев — это игнорирование файлов с определёнными расширениями, как в примере с файлами JavaScript в директории. Давайте подробно рассмотрим, как это сделать, и исправить потенциальные ошибки в шаблонах.
Проблема
У вас есть два файла:
foo/bar/baz/test.js
foo/bar/baz/test.min.js
При исполнении следующей команды вы ожидаете вывести только файл test.js
:
shopt -s globstar
shopt -s extglob
echo foo/bar/**/*!(.min).js
Однако результатом будет:
foo/bar/baz/test.js
foo/bar/baz/test.min.js
Это происходит потому, что шаблон !(.min)
не работает так, как ожидается. Давайте разберемся почему.
Причины проблемы
При использовании шаблона !(.min)
, Bash рассматривает это как "всё, что не является .min
", и к тому же принимает во внимание пустую строку. Таким образом, шаблон будет соответствовать как test.js
, так и test.min.js
, поскольку !(.min)
может совпасть с пустым значением.
Разбор сопоставления
При анализе работы команды, сопоставление может происходить следующим образом:
foo/bar/
соответствуетfoo/bar/
.**/
соответствуетbar/
.*
соответствуетtest.min
.!(.min)
соответствует пустой строке..js
соответствует.js
.
Таким образом, test.min.js
также подходит под данный шаблон.
Решение
Чтобы корректно игнорировать файлы с .min
, нужно использовать другой подход. Вместо !(.min)
используется !(*.min)
, что интерпретируется как "всё, что не заканчивается на .min
". Это позволяет исключить все соответствующие файлы.
Используйте следующий шаблон в вашей команде:
echo foo/bar/**/!(*.min).js
Итоги
Теперь, когда вы выполнили обновлённый шаблон, вы получите правильный результат, исключающий файлы с .min
:
foo/bar/baz/test.js
Рекомендации
- Всегда проверяйте, как ваши шаблоны взаимодействуют с пустыми строками и другими символами.
- Изучайте различные способы использования extglob, чтобы избегать распространённых ошибок в простых сценариях работы с файлами.
- Используйте встроенные возможности Bash, такие как
shopt
, для оптимизации вашего рабочего процесса.
Знание таких нюансов значительно улучшит вашу продуктивность как специалиста в IT и позволит эффективно управлять файлами в системах на основе Unix.