Решение 1
Наиболее близким решением является использование find
с -print0
и читать выход с while read …
:
find -name "*.log" -o -name "*.err" -o -name "*.out" -type f -print0 | while IFS= read -r -d '' logfile; do ...
Продолжайте использовать "$logfile"
с кавычками, как всегда, когда используете переменные.
Решение 2
Другое решение было бы вообще не использовать find
и просто grep
запускать несколько файлов:
shopt -s nullglob shopt -s globstar grep "api/" **/*.log **/*.err **/*.out
Здесь, globstar
позволяет рекурсивное сопоставление каталогов с **
. Вы должны установить, nullglob
чтобы предотвратить ошибки, если одно из этих расширений файлов не существует.
Это работает только для ограниченного набора файлов, так как вы можете достичь максимальной длины аргументов командной строки.
Почему происходит ошибка?
Вы никогда не должны запускаться for
на выходе find
( ls
или любой другой функции, которая выводит имена файлов с пробелами). Прочитайте эту статью для получения дополнительной информации о том, почему это проблема и что можно сделать, чтобы ее решить.
Короче говоря, Bash разделяет аргументы по пробелам. Представьте, у вас есть три файла, a
, foo bar
и b
, то линия будет вычисляться в:
for logfile in a foo bar b; do
Очевидно, что Bash будет установлен logfile
на a
, foo
, bar
, и b
, что не то, что вы хотели. Если бы вы могли вручную указать ввод для for
, вы бы заключили эти имена в кавычки, чтобы решить проблему.
Для того, чтобы сделать это автоматически, решение состоит в том, чтобы разделить эти имена файлов NUL
символом (что и -print0
делает опция), а затем снова разделить выходные данные на основе этого NUL
символа (что и делает -d ''
in read
).