CD у всіх каталогах, виконайте команду над файлами у цьому каталозі та поверніться до попереднього поточного каталогу


41

Я намагаюся написати скрипт, який буде запускатися в заданому каталозі з багатьма однорівневими підкаталогами. Сценарій буде CD в кожному з підкаталогів, виконає команду над файлами в каталозі і cd вийде для продовження наступного каталогу. Який найкращий спосіб зробити це?


1
Зважаючи на поточний рівень наданої інформації, я не бачу ніякого відношення до цього youtube-dl.
HalosGhost

Відповіді:


83
for d in ./*/ ; do (cd "$d" && somecommand); done

12
Отже, оскільки відповідач опустив будь-яке пояснення, я спробую це зробити. for d in ./*/запускає цикл, який зберігає кожен елемент у ./*/(перелік файлів / папок, у цьому випадку) у змінній $d. do (cd "$d" && somecommand);запускається тіло петлі. Всередині корпусу він запускає нижню частину корпусу і виконує команди cdта somecommandкоманди. Оскільки це дочірня оболонка, батьківська оболонка (оболонка, з якої ви виконуєте цю команду) зберігає свої CWD та інші змінні середовища. doneпросто закриває корпус петлі.
Qix

цей метод працює для підкаталогів каталогів:, for d in ./*/ ; do (cd "$d" && ls); doneне працюватиме. але, for d in ./*/ ; do (cd "$d" && for d in ./*/ ; do (cd "$d" && ls); done ); doneбуде працювати. -використання ls як команди в цьому прикладі.
Майкл Діммітт

-bash: cd: ./*/: No such file or directory
S. Tarık Çetin

15

Найкращий спосіб - взагалі не використовувати cd:

find some/dir -type f -execdir somecommand {} \;

execdirяк exec, але робочий каталог інший:

   -execdir command {} [;|+]
          Like   -exec,   but  the  specified  command  is  run  from  the
          subdirectory containing the matched file, which is not  normally
          the  directory  in  which  you  started  find.  This a much more
          secure  method  for  invoking  commands,  as  it   avoids   race
          conditions  during resolution of the paths to the matched files.

Це не POSIX.


Чи працює це з псевдонімами? У мене є один, щоб завантажити певні файли, але він не розпізнає його під час введення знаходження * /. Link -type f -execdir md $ (cat .link) {} \;
Щось Джонс

@SomethingJones ні, findвиконує ці команди, тож псевдоніми не знають. Що таке mdта чи .linkє каталог?
муру

.link - це текстовий файл із URL-адресою, яку він повинен завантажити. md - псевдонім wget з набором набору прапорів. Чи є спосіб зрозуміти псевдоніми?
Щось Джонс

@SomethingJones для вашого конкретного сценарію використання, в bash: find . -type f -iname '*.link' -execdir ${BASH_ALIASES[md]} -i {} \;Вам не потрібно робити catз wget, який має -iпрапор для читання в URL з файлу. Також це дещо відрізняється від вашого оригінального запитання (оскільки вас, здається, цікавлять лише файли з ім'ям, .linkа не будь-які інші файли, які можуть бути присутніми).
муру

Чи знаєте ви, як це зробити з zsh? Я спробував те, що ви мені дали, і я отримую помилку "Погана заміна". Крім того, як я зможу витягнути вміст файлу .link? Я знаю, що мені це не потрібно в цьому випадку, але я думаю, що скоро.
Щось Джонс

2
cd -P .
for dir in ./*/
do cd -P "$dir" ||continue
   printf %s\\n "$PWD" >&2
   command && cd "$OLDPWD" || 
! break; done || ! cd - >&2

Вищевказана команда не потребує жодних підзаголовок - вона просто відстежує її хід у поточній оболонці шляхом чергування $OLDPWDта $PWD. Коли ви cd -оболонка обмінюється значенням цих двох змінних, в основному, оскільки вона змінює каталоги. Він також виводить ім'я для кожного каталогу, оскільки він працює там, щоб stderr.

Я просто по-другому подивився на це і вирішив, що можу зробити кращу роботу з поводженням з помилками. Він пропустить dir, в який він не зможе cd- і cdнадрукує повідомлення про те, чому робити stderr, - і він буде breakбез ненульового коду виходу, якщо ваш файл commandне виконується успішно або якщо запуск commandякимось чином впливає на його здатність повернутися до початкового каталогу - $OLDPWD. У цьому випадку він також виконує cd -останнє - і записує отримане поточне ім'я робочого каталогу в stderr.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.