Использование вывода ls
для получения имен файлов - плохая идея . Это может привести к неправильной работе и даже опасным сценариям. Это происходит потому, что имя файла может содержать любые символы, кроме /
и null
характер, и ls
не использовать один из этих символов в качестве разделителей, так что если имя файла содержит пробел или символ новой строки, вы будете получать неожиданные результаты.
Есть два очень хороших способа перебора файлов. Здесь я использовал просто, echo
чтобы продемонстрировать что-то с именем файла; Вы можете использовать все, что угодно.
Во-первых, использовать встроенные функции оболочки.
for dir in */; do echo "$dir" done
Оболочка расширяется */
в отдельные аргументы, которые for
читает цикл; даже если в имени файла есть пробел, символ новой строки или любой другой странный символ, for
каждое полное имя будет рассматриваться как атомарная единица; это не разбирает список в любом случае.
Если вы хотите рекурсивно переходить в подкаталоги, это не сработает, если ваша оболочка не имеет расширенных функций глобализации (например bash
, s globstar
. Если ваша оболочка не имеет этих функций или если вы хотите убедиться, что ваш скрипт будет работать на различных системах, то следующий вариант заключается в использовании find
.
find . -type d -exec echo '{}' \;
Здесь find
команда вызовет echo
и передаст ей аргумент имени файла. Он делает это один раз для каждого найденного файла. Как и в предыдущем примере, нет разбора списка имен файлов; вместо этого имя файла отправляется полностью в качестве аргумента.
Синтаксис -exec
аргумента выглядит немного забавно. find
принимает первый аргумент после -exec
и обрабатывает его как программу для запуска, а каждый последующий аргумент - как аргумент для передачи этой программе. Есть два особых аргумента, которые -exec
нужно увидеть. Первый из них {}
; этот аргумент заменяется именем файла, которое find
генерирует предыдущие части . Второй ;
, который дает find
понять, что это конец списка аргументов для передачи в программу; find
Это необходимо, потому что вы можете продолжить с большим количеством аргументов, которые предназначены find
и не предназначены для программы exec'd. Причина в том \
, что оболочка также лечит;
специально - она представляет конец команды, поэтому нам нужно избегать ее, чтобы оболочка выдавала ее в качестве аргумента, find
а не использовала ее для себя; Другой способ заставить оболочку не обрабатывать ее специально - заключить ее в кавычки: ';'
работает так же, как и \;
для этой цели.