Проблема не в $file
, а в том, что вы используете $(find…)
.
И регулярные переменные, и подстановки процесса $(…)
подвергаются точно одинаковому типу расщепления слов. Если вы поставите $(find…)
в двойные кавычки, вы получите одно слово со всем выводом. Если вы этого не сделаете, он будет разбит на любые пустые места - не только на новые строки или какие-то другие магические границы, которые вы, вероятно, ожидали.
Важной частью вышесказанного является то, что обратные слэши не обрабатываются при расширении переменной. Это просто разделено на пробелы и все.
(Другими словами, цитирование $file
не помогло, потому что оно никогда не имело правильного значения в первую очередь!)
Если вы хотите обрабатывать все файлы рекурсивно, ваши варианты:
Прочитать вывод из find
другим способом:
find … -print | while read -r file; do
echo "Got $file"
done
(Примечание стороны: имена файлов могут технически включать в себя новые строки, так что вы можете захотеть , чтобы защититься от этого, так же редки , как это:
find … -print0 | while read -r -d "" file; do
echo "Got $file"
done
Для небольшого количества файлов используйте расширенные символы подстановки bash:
shopt -s globstar
for file in /path/to/foo/**; do
echo "Got $file"
done
С большими каталогами, преимущество find | while read
означает, что он транслируется - ваш скрипт будет обрабатывать результаты по мере их поступления. Между тем, и $(find)
и подстановочные знаки должны сначала собирать все в память, а только потом возвращать (возможно, массивные) результаты.
С другой стороны, использование трубы влияет на весь во while
цикла ( а не только команда read
так что если вы хотите запустить что - нибудь , что хочет читать ввод с клавиатуры, вам придется вручную предоставить его с оригинальным стандартного ввода, например , vim "$file" < /dev/tty
.