Я думал, что это будет просто - но это оказывается сложнее, чем я ожидал.
Я хочу перебрать все файлы определенного типа в каталоге, поэтому я пишу это:
#!/bin/bash
for fname in *.zip ; do
echo current file is ${fname}
done
Это работает до тех пор, пока в каталоге есть хотя бы один соответствующий файл . Однако, если нет подходящих файлов, я получаю это:
current file is *.zip
Я тогда попробовал:
#!/bin/bash
FILES=`ls *.zip`
for fname in "${FILES}" ; do
echo current file is ${fname}
done
Хотя тело цикла не выполняется, когда нет файлов, я получаю сообщение об ошибке от ls:
ls: *.zip: No such file or directory
Как мне написать цикл, который чисто обрабатывает не соответствующие файлы?
shopt -s nullglob
перед запуском цикла for.FILES=
ls * .zip,; for fname in "${FILES}"...
но он работает, как и ожидалось, сfor fname in *.zip ; do....
for file in *.zip
, нет`ls ...`
. Предложение @ cuonglm таково, что*.zip
расширяется до нуля, когда шаблон не соответствует ни одному файлу.ls
без аргументов перечисляет текущий каталог.ls
вообще следует избегать синтаксического анализа выходных данных : почему бы неls
выполнить синтаксический анализ ? ; также смотрите ссылку в верхней части этой страницы на статью BashGuide's ParsingLs .Ответы:
В
bash
, вы можете установитьnullglob
опцию так, чтобы шаблон, который ничего не соответствует, «исчезал», а не рассматривался как литеральная строка:В сценарии оболочки POSIX вы просто проверяете, что
fname
существует (и в то же время[ -f ]
проверяете, что это обычный файл (или символическая ссылка на обычный файл), а не другие типы, такие как directory / fifo / device ...):Замените
[ -f "$fname" ]
на,[ -e "$fname" ] || [ -L "$fname ]
если вы хотите перебрать все (не скрытые) файлы, имя которых заканчивается.zip
независимо от их типа.Замените
*.zip
на,.*.zip .zip *.zip
если вы также хотите рассмотреть скрытые файлы, имя которых заканчивается на.zip
.источник
shopt -s nullglob
не работал у меня на Ubuntu 17.04, но[ -f "$fname" ] || continue
работал хорошо.bash
.В комментарии здесь вы упоминаете вызов функции ...
источник
Используйте найти
Вы ДОЛЖНЫ экспортировать свою функцию оболочки,
export -f
чтобы это работало.find
Выполняет теперь,bash
что выполняет вашу функцию оболочки, и остается только на текущем уровне каталога.источник
Вместо того:
Пытаться:
Таким образом, если ls завершится неудачно (что и происходит в вашем случае), он выдаст сбойный вывод и вернется в виде пустой переменной.
Вы можете добавить к этому логику, чтобы она возвращала «Файл не найден»
Таким образом, если предыдущая команда была выполнена успешно (выход со значением 0), она напечатает текущий файл, в противном случае будет напечатано «Файлы не найдены»
источник
grep
) вместо того, чтобы пытаться исправить проблему, используя лучший инструмент (find
) или изменив соответствующие настройки для текущего решения (сshopt -s nullglob
)shopt -s nullglob
, не работает. Я пыталсяfind
проверить мой ответ, и он продолжал терпеть неудачу. Я думаю из-за экспорта, что сказал Дани.