Хотя здесь может быть полезно использование команды find
, сама оболочка предоставляет параметры для выполнения этого требования без каких-либо сторонних инструментов. Оболочка bash
предоставляет расширенную опцию поддержки glob, с помощью которой вы можете получить имена файлов по рекурсивным путям, которые соответствуют нужным вам расширениям.
Расширенный параметр - extglob
, который необходимо установить с помощью параметра shopt
, как показано ниже. Параметры включены с помощью поддержки -s
и отключены с помощью флага -u
. Кроме того, вы можете использовать еще несколько параметров, например nullglob
, в котором несоответствующий глобус полностью удаляется и заменяется набором нулевых слов. И globstar
, что позволяет рекурсивно просматривать все каталоги
shopt -s extglob nullglob globstar
Теперь все, что вам нужно сделать, это сформировать глобальное выражение для включения файлов определенного расширения, что вы можете сделать, как показано ниже. Мы используем массив для заполнения результатов glob, потому что при правильном цитировании и расширении имена файлов со специальными символами останутся нетронутыми и не будут повреждены из-за разделения слов оболочкой.
Например, чтобы перечислить все файлы *.csv
в рекурсивных путях
fileList=(**/*.csv)
Параметр **
- это рекурсивный просмотр подпапок, а *.csv
- расширение глобуса для включения любого файла с упомянутыми расширениями. Теперь для печати фактических файлов просто выполните
printf '%s\n' "${fileList[@]}"
Использование массива и правильное расширение кавычек - правильный путь при использовании в сценариях оболочки, но для интерактивного использования вы можете просто использовать ls
с выражением glob как
ls -1 -- **/*.csv
Это вполне может быть расширено для соответствия нескольким файлам, то есть файлу, заканчивающемуся несколькими расширениями (то есть аналогично добавлению нескольких флагов в команде find
). Например, рассмотрим случай, когда вам нужно получить все файлы рекурсивных изображений, то есть с расширениями *.gif
, *.png
и *.jpg
, все, что вам нужно, это
ls -1 -- **/+(*.jpg|*.gif|*.png)
Это вполне может быть расширено, чтобы также иметь отрицательные результаты. С таким же синтаксисом можно использовать результаты glob для исключения файлов определенного типа. Предположим, вы хотите исключить имена файлов с указанными выше расширениями, вы можете сделать
excludeResults=()
excludeResults=(**/!(*.jpg|*.gif|*.png))
printf '%s\n' "${excludeResults[@]}"
Конструкция !()
представляет собой операцию отрицания, чтобы не включать какие-либо расширения файлов, перечисленные внутри, а |
- это оператор чередования, который используется в библиотеке расширенных регулярных выражений для сопоставления глобусов по ИЛИ.
Обратите внимание, что эта расширенная поддержка глобусов недоступна в оболочке POSIX bourne и является специфической только для последних версий bash
. Поэтому, если вы рассматриваете возможность переноса скриптов, работающих в оболочках POSIX и bash
, этот вариант будет неправильным.
Ошибка из-за отсутствия символа "{"
Этот вопрос является дубликатом Как я могу рекурсивно найти все файлы в текущей и подпапках на основе сопоставления подстановочных знаков?