Я пытаюсь найти все файлы с определенным расширением в каталоге и его подкаталогах с помощью моего bash (последняя версия Ubuntu LTS).
Вот что написано в файле скрипта:
#!/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"
К сожалению, когда я запускаю этот скрипт в терминале, он говорит:
[: 29: in: unexpected operator
(с $extension
вместо 'in'
)
Что здесь происходит, где ошибка? Но эта фигурная скобка
Без использования find
:
du -a $directory | awk '{print $2}' | grep '\.in
browsefolders ()
{
. Все $in
должны быть $suffix
cut
дает вам только среднюю часть front.middle.extension
. Вы должны прочитать руководство по оболочке на ${varname%%pattern}
и у друзей. Я предполагаю, что вы делаете это как упражнение в написании сценариев оболочки, в противном случае уже предложенное решение find
- это путь.
Для проверки правильности синтаксиса оболочки без запуска сценария используйте sh -n scriptname
.
Синтаксис, который я использую, немного отличается от предложенного @Matt:
find $directory -type f -name \*.in
(это на одно нажатие клавиши меньше).
for file in "${LOCATION_VAR}"/*.zip
do
echo "$file"
done
find $directory -type f -name "*.in"
немного короче всего этого (и безопаснее - имеет дело с пробелами в именах файлов и каталогов).
Возможно, ваш скрипт не работает для записей, в имени которых нет .
, что делает $extension
пустым.
createHTMLDocument
обещание взглядов, если это weren' t для ограниченной поддержки. Синтаксические анализаторы HTML являются хорошими предложениями, хотя немного тяжелы, поскольку я предполагаю, что простой regex мог удалить src из изображения и продвинуть те данные на свойство элементов т.е. src2
так it' s все еще применимый. Я предполагаю, что надеялся на волшебное свойство, которое остановило это предварительно загружающее поведение, похож на более грязную фиксацию, необходим. Кроме того, иногда служа в другом формате isn' t возможный, т.е. для использования в сценарии Механика.
– Gary Green
19.11.2019, 07:03
find
является рекурсивным по умолчанию. можно ограничить глубины, если Вы хотите (см. страницу справочника).
– Mat
14.03.2020, 16:11
Хотя здесь может быть полезна команда 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[@]}"
Конструкция !()
является операцией отрицания, которая не включает в себя какие-либо расширения файлов, перечисленные внутри, и |
является чередованием оператор, аналогичный тому, который используется в библиотеке расширенных регулярных выражений для сопоставления ИЛИ глобусов.
Обратите внимание, что эта расширенная поддержка glob недоступна в оболочке POSIX bourne и является чисто специфической для последних версий bash
. Так что, если вы рассматриваете переносимость сценариев, работающих в оболочках POSIX и bash
, эта опция будет неправильной.