Есть ли у кого-нибудь шаблонный скрипт для работы с ls
списком имен каталогов, циклический просмотр каждого из них и выполнение чего-либо?
Я планирую сделать, ls -1d */
чтобы получить список имен каталогов.
источник
Есть ли у кого-нибудь шаблонный скрипт для работы с ls
списком имен каталогов, циклический просмотр каждого из них и выполнение чего-либо?
Я планирую сделать, ls -1d */
чтобы получить список имен каталогов.
Отредактировано, чтобы не использовать ls там, где будет делать глоб, как предложили @ shawn-j-goff и другие.
Просто используйте for..do..done
цикл:
for f in *; do
echo "File -> $f"
done
Вы можете заменить *
с *.txt
или любой другой Glob , который возвращает список (файлов, каталогов или что - нибудь в этом отношении), команда , которая генерирует список, например, $(cat filelist.txt)
или на самом деле заменить его в списке.
Внутри do
цикла вы просто ссылаетесь на переменную цикла с префиксом знака доллара (как $f
в приведенном выше примере). Вы можете echo
сделать это или сделать что-то еще, что хотите.
Например, чтобы переименовать все .xml
файлы в текущем каталоге .txt
:
for x in *.xml; do
t=$(echo $x | sed 's/\.xml$/.txt/');
mv $x $t && echo "moved $x -> $t"
done
Или даже лучше, если вы используете Bash, вы можете использовать расширения параметров Bash, а не порождать подоболочку:
for x in *.xml; do
t=${x%.xml}.txt
mv $x $t && echo "moved $x -> $t"
done
for
циклов и типичную ловушку при попытке анализа выходных данныхls
. @ DanielA.Белый, вы можете подумать о том, чтобы не принять этот ответ, если он не помог (или потенциально вводит в заблуждение), поскольку, как вы сказали, вы действуете по каталогам. Ответ Шона Дж. Гоффа должен обеспечить более надежное и эффективное решение вашей проблемы.ls
вывод , вы не должны читать вывод вfor
цикле , вы должны использовать$()
вместо `` и Use More Quotes ™ . Я уверен, что @CoverosGene имел в виду хорошо, но это просто ужасно.ls
этоls -1 | while read line; do stuff; done
. По крайней мере, это не сломается для пробелов.mv -v
тобой не надоecho "moved $x -> $t"
Использование вывода
ls
для получения имен файлов - плохая идея . Это может привести к неправильной работе и даже опасным сценариям. Это происходит потому , что имя файла может содержать любые символы , кроме/
иnull
характер, иls
не использовать один из этих символов в качестве разделителей, так что если имя файла содержит пробел или символ новой строки, вы будете получать неожиданные результаты.Есть два очень хороших способа перебора файлов. Здесь я просто
echo
продемонстрировал, как что-то делать с именем файла; Вы можете использовать все, что угодно.Во-первых, использовать встроенные функции оболочки.
Оболочка расширяется
*/
в отдельные аргументы, которыеfor
читает цикл; даже если в имени файла есть пробел, символ новой строки или любой другой странный символ,for
каждое полное имя будет рассматриваться как атомарная единица; это не разбирает список в любом случае.Если вы хотите рекурсивно переходить в подкаталоги, то этого не произойдет, если ваша оболочка не имеет некоторых расширенных функций глобализации (например
bash
, sglobstar
. Если ваша оболочка не имеет этих функций или если вы хотите убедиться, что ваш скрипт будет работать на различных системах, то следующий вариант заключается в использованииfind
.Здесь
find
команда вызоветecho
и передаст ей аргумент имени файла. Он делает это один раз для каждого найденного файла. Как и в предыдущем примере, нет разбора списка имен файлов; вместо этого имя файла отправляется полностью в качестве аргумента.Синтаксис
-exec
аргумента выглядит немного забавно.find
принимает первый аргумент после-exec
и обрабатывает его как программу для запуска, а каждый последующий аргумент - как аргумент для передачи этой программе. Есть два особых аргумента, которые-exec
нужно увидеть. Первый из них{}
; этот аргумент заменяется именем файла, котороеfind
генерирует предыдущие части . Второй;
, который даетfind
понять, что это конец списка аргументов для передачи в программу;find
Это необходимо, потому что вы можете продолжить с дополнительными аргументами, которые предназначеныfind
и не предназначены для программы exec'd. Причина в том\
, что оболочка также лечит;
специально - она представляет конец команды, поэтому нам нужно избегать ее, чтобы оболочка выдавала ее в качестве аргумента,find
а не использовала ее для себя; Другой способ заставить оболочку не обрабатывать ее специально - заключить ее в кавычки:';'
работает так же, как и\;
для этой цели.источник
find
. Есть волшебство, которое можно сделать, и даже воспринимаемые ограничения-exec
можно обойти.-print0
Вариант также ценен для использования сxargs
.Для файлов с пробелами вы должны обязательно заключить в кавычки переменную, например:
или вы можете изменить переменную среды разделителя входных полей (IFS):
Наконец, в зависимости от того, что вы делаете, вам может даже не понадобиться ls:
источник
\n
недостаточен. Никогда не рекомендуется рекомендовать анализ выходных данныхls
.Если у вас установлен GNU Parallel http://www.gnu.org/software/parallel/, вы можете сделать это:
Чтобы переименовать все .txt в .xml:
Посмотрите вступительное видео для GNU Parallel, чтобы узнать больше: http://www.youtube.com/watch?v=OpaiGYxkSuQ
источник
Просто чтобы добавить ответ CoverosGene, вот способ перечислить только имена каталогов:
источник
Почему бы не установить IFS на новую строку, а затем записать вывод
ls
в массив? Установка IFS на новую строку должна решить проблемы с забавными символами в именах файлов; Использованиеls
может быть хорошим, потому что оно имеет встроенную функцию сортировки.(При тестировании у меня возникли проблемы с настройкой IFS,
\n
но настройка перевода строки на новую строку работает, как это предлагается в другом месте здесь):Например (при условии, что желаемый
ls
шаблон поиска передан$1
):Это особенно удобно в OS X, например, для захвата списка файлов, отсортированных по дате создания (от самого старого до самого нового),
ls
команда имеет видls -t -U -r
.источник
\n
недостаточен. Единственные допустимые решения используют цикл for с расширением пути илиfind
.Вот как я это делаю, но, возможно, есть более эффективные способы.
источник
ls | while read i; do echo filename: $i; done