TL; DR: Якщо ви просто тут для найправильнішої відповіді, ви, мабуть, хочете моїх особистих уподобань find . -name '*.txt' -exec process {} \;
(див. Внизу цієї публікації). Якщо у вас є час, прочитайте решту, щоб побачити кілька різних способів та проблеми з більшістю з них.
Повна відповідь:
Найкращий спосіб залежить від того, що ви хочете зробити, але ось кілька варіантів. Поки жоден файл чи папка в піддереві не має пробілу у своєму імені, ви можете просто перекинути файли:
for i in $x; do # Not recommended, will break on whitespace
process "$i"
done
Краще, виріжте тимчасову змінну x
:
for i in $(find -name \*.txt); do # Not recommended, will break on whitespace
process "$i"
done
Це набагато краще Glob , коли ви можете. Безпечний простір для файлів у поточному каталозі:
for i in *.txt; do # Whitespace-safe but not recursive.
process "$i"
done
Ввімкнувши globstar
опцію, ви можете розмістити всі відповідні файли в цьому каталозі та всі підкаталоги:
# Make sure globstar is enabled
shopt -s globstar
for i in **/*.txt; do # Whitespace-safe and recursive
process "$i"
done
У деяких випадках, наприклад, якщо імена файлів уже є у файлі, можливо, вам доведеться використовувати read
:
# IFS= makes sure it doesn't trim leading and trailing whitespace
# -r prevents interpretation of \ escapes.
while IFS= read -r line; do # Whitespace-safe EXCEPT newlines
process "$line"
done < filename
read
можна безпечно використовувати в поєднанні з find
, якщо правильно встановити роздільник:
find . -name '*.txt' -print0 |
while IFS= read -r -d '' line; do
process "$line"
done
Для більш складних пошукових запитів ви, мабуть, захочете скористатися find
або з його -exec
опцією, або з-print0 | xargs -0
:
# execute `process` once for each file
find . -name \*.txt -exec process {} \;
# execute `process` once with all the files as arguments*:
find . -name \*.txt -exec process {} +
# using xargs*
find . -name \*.txt -print0 | xargs -0 process
# using xargs with arguments after each filename (implies one run per filename)
find . -name \*.txt -print0 | xargs -0 -I{} process {} argument
find
також можна вписати в каталог кожного файлу перед запуском команди, використовуючи -execdir
замість -exec
, і можна зробити інтерактивним (підказка перед запуском команди для кожного файлу), використовуючи -ok
замість-exec
(або -okdir
замість -execdir
).
*: Технічно обидва find
та xargs
(за замовчуванням) виконують команду з якомога більше аргументів, скільки їх може вміститися в командному рядку стільки разів, скільки потрібно, щоб пройти всі файли. На практиці, якщо у вас дуже велика кількість файлів, це не має значення, і якщо ви перевищуєте довжину, але потрібні вони всі в одному командному рядку, ви SOL знайдете інший спосіб.