Как вводить каждый каталог в текущий путь и выполнять скрипт

Я хочу ввести каждый каталог, перенастроенный командой ls и выполнить скрипт.

Я пробовал это (и многое другое), но он просто не работает

ls  | awk '{print $1" && pwd"}' | xargs cd

Как сделать это без цикла?

1
задан 11 June 2014 в 05:12

6 ответов

find . -type d -exec bash -c 'cd "$0" && pwd' {} \;

Смените pwd для своего скрипта. И . для имени корневого каталога, если это не «текущий» каталог.

Вы должны обернуть предложение exec в bash -c "..." из-за того, как работает -exec. cd не существует в его ограниченной среде, но, как вы можете видеть, запустив приведенную выше команду, когда вы приводите bash для выполнения задания, все работает так, как было предсказано.

Edit: I'm не уверен, почему 2011 Оли не думал о -execdir, но это, вероятно, более быстрое решение:

find . -type d -execdir pwd \;
13
ответ дан 25 May 2018 в 17:02
  • 1
    Причина cd сама по себе не работает, потому что это встроенная оболочка, не имеющая ничего общего с окружающей средой. – enzotib 9 November 2011 в 21:07
  • 2
    Хорошая работа Оли. Я добавил maxdepth здесь, как упоминалось ранее, также, поскольку он, по-видимому, подразумевает текущие подкаталоги, которые я удалил .: find . -maxdepth 1 -type d \( ! -name . \) -exec bash -c "cd '{}' && pwd" \; – Todd Partridge 'Gen2ly' 29 May 2012 в 21:59

Команда find

Команда find довольно удобна. Он может генерировать список файлов или директив в или ниже указанного каталога, а также может выполнять команду для каждого элемента в этом списке результатов. (Примечание: если вы используете многопользовательскую систему, обязательно прочитайте раздел соображений безопасности документации Findutils для команды find.)

Параметры команды find, которые нам нужны, тип 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. может быть, это поможет u

2
ответ дан 25 May 2018 в 17:02
  • 1
    Не нужно указывать {}, а -maxdepth 1 может быть полезна, если OP не хочет переписывать в подкаталоги. – enzotib 9 November 2011 в 21:11
  • 2
    @enzotib Я не знал о -maxdepth 1, thx – UAdapter 9 November 2011 в 21:42

Просто для любопытства я попытался взять ваш пример и заставить его работать. Нет смысла использовать эту технику вместо команды find.

Примечание: благодаря указанию enzotib, это не работает для имен каталогов, содержащих пробелы или любые другие символы, которые делают awk считают, что имя состоит из нескольких полей.

Чтобы сделать ваш пример, нужно сделать несколько настроек. Но сначала посмотрите на код:

ls -l | grep ^d | awk '{print $NF}' | xargs -n 1 bash -c 'cd $0; ls'

Первые две команды удостоверяются, что перечислены только каталоги. Поскольку длинный список ls содержит d в качестве первого символа для каталогов, команда grep выбирает только эти строки.

С awk в каждой строке отображается только последний столбец. NF - встроенная переменная в awk, содержащая максимальное количество полей. Таким образом, печать $NF отображает последнее поле.

Наконец, xargs необходимо приручить для запуска указанного скрипта только с одним параметром. (Я знаю этот вид - поражения его цели.) В противном случае сценарий не мог быть запущен для каждого каталога без цикла for.

И чтобы обойти встроенный барьер cd, мы вызываем [ f13] с -c. Также обратите внимание, что $0 становится первым параметром вместо $1.

2
ответ дан 25 May 2018 в 17:02
  • 1
    К сожалению, если у вас есть имена каталогов, содержащие пробелы, $NF дает только последнее слово имени. Это одна из причин, почему людям предлагается не анализировать выход ls. – enzotib 9 November 2011 в 21:15
  • 2
    Это допустимая точка, и я не вижу легкого обходного пути, не создавая длинный скрипт awk. Я пытался показать, как может работать оригинальное мышление (и убедить OP не использовать его, потому что это, по крайней мере, не изящно). Спасибо, что указали это, я обновлю ответ. – lgarzo 9 November 2011 в 21:23
  • 3
    См. Мой ответ с xargs. – enzotib 9 November 2011 в 21:43
  • 4
    thx много, я изучаю bash, и это очень полезно. – UAdapter 10 November 2011 в 15:40

Возможно, взгляните на использование find с -exec?

2
ответ дан 25 May 2018 в 17:02

Другая альтернатива:

for directory in *
do
  (cd $directory && awk '{print $1" && pwd"}')
done
2
ответ дан 25 May 2018 в 17:02

Вы не должны разбирать ls в первую очередь.

Вы можете использовать для этого и его -execdir параметр GNU find, например:

find . -type d -execdir realpath "{}" ';'

] или более практичный пример:

find . -name .git -type d -execdir git pull -v ';'

и здесь версия с -exec:

find . -type d -print0 | xargs -0 -I% sh -c 'cd "%" && pwd && echo Do stuff'

Дополнительные примеры см. в: не должны разбираться ls в SO

1
ответ дан 25 May 2018 в 17:02

Другие вопросы по тегам:

Похожие вопросы: