Рекурсивно перебирать файлы в каталоге можно легко:
find . -type f -exec bar {} \;
Тем не менее, вышеописанное не работает для более сложных вещей, где необходимо выполнить много условных переходов, циклов и т. Д. Я использовал это для вышеупомянутого:
while read line; do [...]; done < <(find . -type f)
Однако, похоже, что это не работает для файлов, содержащих непонятные символы:
$ touch $'a\nb'
$ find . -type f
./a?b
Есть ли альтернатива, которая хорошо справляется с такими непонятными персонажами?
find ... -exec bash -c 'echo filename is in \$0: "$0"' {} \;
это лучший способ сделать это.read line
наIFS= read -r line
. Единственный символ, который сломает это тогда, является новой строкой.-d $'\0'
предпочтительнее.Ответы:
Еще одно использование для безопасности
find
:(Это работает с любым POSIX
find
, но часть оболочки требует bash. С * BSD и GNU find вы можете использовать-print0
вместо-exec printf '%s\0' {} +
, это будет немного быстрее.)Это позволяет использовать стандартный ввод в цикле, и он работает с любым путем.
источник
do echo "Filename is '$REPLY'"
Сделать это так же просто, как:
Или...
источник
Самый простой (но безопасный) подход заключается в использовании глобализации оболочки:
Чтобы превратить вышеперечисленное в подкаталоги (в bash), вы можете использовать
globstar
опцию; также установитьdotglob
соответствие файлам, чье имя начинается с.
:Остерегайтесь, что до bash 4.2,
**/
рекурсивные ссылки на каталоги. Начиная с bash 4.3,**/
рекурсивно только в каталогах, вродеfind
.Другое распространенное решение заключается в использовании
find -print0
сxargs -0
:Обратите внимание, что
h:/g
это действительно правильно, так как имя файла содержит\r
.источник
Это немного сложно сделать ваш цикл чтения переносимым, но для bash, в частности, вы можете попробовать что-то вроде этого .
Соответствующая часть:
Это инструктирует
find
выводить выходные данные, разделенные символами NUL (0x00), иread
извлекать строки, разделенные NUL (-d $'\0'
), не обрабатывая обратную косую черту как экранирование для других символов (-r
), и не разбивать слова на строки (IFS=
). Поскольку 0x00 - это байт, который не может встречаться в именах файлов или путях в Unix, это должно решить все ваши странные проблемы с именами файлов.источник
-d ''
эквивалентно-d $'\0'
.