Я хочу войти в каждый каталог, перенастроенный командой ls
, и выполнить скрипт.
Я пытался это (и многие другие), но это просто не работает
ls | awk '{print $1" && pwd"}' | xargs cd
Как это сделать без цикла for?
Если Вы можете, использовать find
как предложено в других ответах, xargs
должен почти всегда избегаться.
Но если Вы все еще хотите использовать xargs
, возможная альтернатива следующая:
printf '%s\0' */ | xargs -0 -L1 bash -c 'cd -- "$1" && pwd' _
Некоторые примечания:
*/
расширяется до списка каталогов в текущей папке, благодаря запаздывающей наклонной черте
printf
с \0
(пустой байт), разделяет элементы один для каждой строки
опция -L1
кому: xargs
добирается выполняются однажды для каждой входной строки и опции -0
заставляет его разделить вход на пустом байте: имена файлов могут содержать любой символ, команда не повреждается!
bash
удаляет двойные кавычки, и передайте его встроенному сценарию как единственный параметр, но cd
должен поместить двойные кавычки снова для интерпретации его как единственной строки; использование --
делает cd
команда, устойчивая против имен файлов, которые запускаются с дефиса
избегать странного использования $0
в качестве параметра, обычно для помещения первого фиктивного аргумента _
find . -type d -exec bash -c 'cd "$0" && pwd' {} \;
Подкачка pwd
для Вашего сценария. И .
для имени корневого каталога, если это не "текущий" каталог.
Необходимо перенести исполнительный пункт в bash -c "..."
из-за пути -exec
работы. cd
не существует в его ограниченной среде, но как Вы видите путем выполнения вышеупомянутой команды при введении удара, чтобы сделать задание, все работает, как предсказано.
Править: Я не уверен, почему 2 011 Oli не думали -execdir
но это - вероятно, более быстрое решение:
find . -type d -execdir pwd \;
Команда поиска
Команда поиска очень удобна. Он может генерировать список файлов или каталогов в или ниже указанного каталога, а также может выполнять команду для каждого элемента в этом списке результатов. (Примечание: если вы используете многопользовательскую систему, обязательно ознакомьтесь с разделом соображений безопасности документации Findutils для команды find.)
Нам нужны следующие опции команды find: -type d, в котором команда find возвращает имена всех каталогов в указанном пути, и команда -exec '{}' \; который сообщает команда find для запуска результатов. Например:
find /media/music/flac -type d -exec ~/tag-flac-with-rg.sh '{}' \;
Это говорит find найти все каталоги в или ниже пути / media / music / flac и затем запустить скрипт tag-flac-with-rg.sh для каждого найденного каталога. '{}' Заменяется каждым найденным именем каталога и передается в качестве аргумента в скрипт tag-flac-with-rg.sh. \; отмечает конец списка аргументов в сценарии tag-flac-with-rg.sh. может быть, это поможет вам
Только для любопытства я пытался взять Ваш пример и заставить его работать. Нет никакой причины использовать эту технику вместо find
команда.
Примечание: Благодаря enzotib для указания на него это не работает на имена каталогов, содержащие пробелы или любые другие символы, которые делают
awk
думайте, что имя состоит из нескольких полей.
Чтобы заставить Ваш пример работать, несколько тонких настроек должны быть сделаны. Но сначала см. код:
ls -l | grep ^d | awk '{print $NF}' | xargs -n 1 bash -c 'cd $0; ls'
Первые две команды удостоверяются, что только каталоги перечислены. С тех пор ls
длинный список содержит a d
как первый символ для каталогов, grep
команда выбирает только эти строки.
С awk
только последний столбец отображен в каждой строке. NF
встроенная переменная в awk
содержание максимального количества полей. Таким образом печать $NF
отображает последнее поле.
Наконец xargs
должен был быть приручен для запущения указанного скрипта только с одним параметром за один раз. (Я знаю, что это отчасти побеждает его цель.) Иначе скрипт не мог быть запущен для каждого каталога без для цикла.
И работать вокруг встроенного cd
барьер, мы звоним bash
с -c
. Также отметьте это $0
становится первым параметром вместо $1
.
Вы не должны анализировать ls
в первую очередь.
Вы можете использовать GNU find
для этого и его параметра -execdir
, например:
find . -type d -execdir realpath "{}" ';'
или более практический пример:
find . -name .git -type d -execdir git pull -v ';'
и вот версия с [ 116]:
find . -type d -print0 | xargs -0 -I% sh -c 'cd "%" && pwd && echo Do stuff'
Дополнительные примеры см .: Как перейти в каждый каталог и выполнить команду? в SO
Другая альтернатива:
for directory in *
do
(cd $directory && awk '{print $1" && pwd"}')
done
Может быть, посмотрите на использование find
с -exec
?