Рекурсивно искать файлы с определенным расширением
Я пытаюсь найти все файлы с определенным расширением в каталоге и его подкаталогах с помощью моего bash (последний выпуск Ubuntu LTS).
Это то, что написано в файле script:
#!/bin/bash
directory="/home/flip/Desktop"
suffix="in"
browsefolders ()
for i in "$1"/*;
do
echo "dir :$directory"
echo "filename: $i"
# echo ${i#*.}
extension=`echo "$i" | cut -d'.' -f2`
echo "Erweiterung $extension"
if [ -f "$i" ]; then
if [ $extension == $suffix ]; then
echo "$i ends with $in"
else
echo "$i does NOT end with $in"
fi
elif [ -d "$i" ]; then
browsefolders "$i"
fi
done
}
browsefolders "$directory"
К сожалению, когда я запускаю этот script в терминале, он говорит:
[: 29: in: unexpected operator
(с $extension
вместо 'in'
)
Что происходит здесь, где ошибка?
Но эта фигурная скобка
Ответы
Ответ 1
find $directory -type f -name "*.in"
немного короче, чем все это (и безопаснее - имеет дело с пробелами в именах файлов и именах каталогов).
Вероятно, ваш script не подходит для записей, у которых нет имени .
в имени, что делает $extension
пустым.
Ответ 2
find {directory} -type f -name '*.extension'
Пример для поиска всех CSV файлов в текущем каталоге и его подкаталогах
find . -type f -name '*.csv'
Ответ 3
Синтаксис, который я использую, немного отличается от того, что предложил @Matt:
find $directory -type f -name \*.in
(это еще одно нажатие клавиши).
Ответ 4
Без использования find
:
du -a $directory | awk '{print $2}' | grep '\.in$'
Ответ 5
- Там
{
отсутствует browsefolders ()
- Все
$in
должны быть $suffix
- Строка с
cut
получает только среднюю часть front.middle.extension
. Вы должны прочитать руководство по работе с оболочкой ${varname%%pattern}
и друзей.
Я предполагаю, что вы выполняете это как упражнение в сценариях оболочки, в противном случае предлагаемое решение find
- это путь.
Чтобы проверить правильность синтаксиса оболочки, без запуска script, используйте sh -n scriptname
.
Ответ 6
Чтобы найти все pom.xml
файлы в вашем текущем каталоге и распечатать их, вы можете использовать:
find . -name 'pom.xml' -print
Ответ 7
Хотя использование команды find
может быть полезно здесь, сама оболочка предоставляет опции для выполнения этого требования без каких-либо сторонних инструментов. Оболочка bash
предоставляет расширенную опцию поддержки glob, с помощью которой вы можете получить имена файлов по рекурсивным путям, которые соответствуют нужным расширениям.
Расширенной опцией является extglob
который необходимо установить с shopt
опции shopt
как shopt
ниже. Опции активируются с поддержкой -s
и отключаются с -u
флага -u
. Кроме того, вы можете использовать несколько опций больше, например, nullglob
в котором непревзойденный nullglob
, заменяется набором нулевых слов. И globstar
который позволяет проходить через все каталоги
shopt -s extglob nullglob globstar
Теперь все, что вам нужно сделать, это сформировать выражение glob для включения файлов с определенным расширением, которые вы можете сделать, как показано ниже. Мы используем массив для заполнения результатов глоба, потому что при правильном цитировании и расширении имена файлов со специальными символами останутся нетронутыми и не сломаются из-за вставки слова -s оболочкой.
Например, чтобы перечислить все файлы *.csv
в рекурсивных путях
fileList=(**/*.csv)
Опция **
состоит в том, чтобы проходить через подпапки, а *.csv
- расширение glob, чтобы включить любой файл упомянутых расширений. Теперь для печати реальных файлов, просто сделайте
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[@]}"
Конструкция !()
- это операция отрицания, которая не включает в себя расширения файлов, перечисленные внутри и |
является оператором чередования, который используется в библиотеке расширенных регулярных выражений для сопоставления ИЛИ глобанов.
Обратите внимание, что эта расширенная поддержка glob недоступна в оболочке POSIX bourne и является чисто специфической для последних версий bash
. Так что, если вы рассматриваете переносимость сценариев, работающих в POSIX и оболочках bash
, этот вариант будет неправильным.
Ответ 8
find $directory -type f -name "*.in"|grep $substring
Ответ 9
for file in "${LOCATION_VAR}"/*.zip
do
echo "$file"
done
Ответ 10
find "$PWD" -type f -name "*.in"