Odpowiedzi:
for d in ./*/ ; do (cd "$d" && somecommand); done
for d in ./*/
uruchamia pętlę, w której zapisywany jest każdy element ./*/
(w tym przypadku lista plików / folderów) w zmiennej $d
. do (cd "$d" && somecommand);
uruchamia ciało pętli. Wewnątrz ciała uruchamia podpowłokę i uruchamia polecenia cd
i somecommand
. Ponieważ jest to powłoka podrzędna, powłoka nadrzędna (powłoka, z której uruchamiane jest to polecenie), zachowuje CWD i inne zmienne środowiskowe. done
po prostu zamyka korpus pętli.
for d in ./*/ ; do (cd "$d" && ls); done
nie będzie działać. ale for d in ./*/ ; do (cd "$d" && for d in ./*/ ; do (cd "$d" && ls); done ); done
zadziała. -korzystanie z ls jako polecenia w tym przykładzie.
-bash: cd: ./*/: No such file or directory
Najlepszym sposobem jest w ogóle nie używać cd
:
find some/dir -type f -execdir somecommand {} \;
execdir
jest jak exec
, ale katalog roboczy jest inny:
-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.
To nie jest POSIX.
find
wykonuje te polecenia, więc nie byłby świadomy aliasów. Co to md
jest .link
katalog?
bash
: find . -type f -iname '*.link' -execdir ${BASH_ALIASES[md]} -i {} \;
Nie trzeba robić cat
z wget
, który ma -i
flagę do czytania w URL z pliku. Również nieco różni się to od twojego pierwotnego pytania (ponieważ wydaje się, że jesteś zainteresowany tylko nazwanymi plikami, .link
a nie innymi, które mogą być obecne).
cd -P .
for dir in ./*/
do cd -P "$dir" ||continue
printf %s\\n "$PWD" >&2
command && cd "$OLDPWD" ||
! break; done || ! cd - >&2
Powyższe polecenie nie musi wykonywać żadnych podpowłok - po prostu śledzi swoje postępy w bieżącej powłoce na przemian $OLDPWD
i $PWD
. Kiedy ty cd -
powłoka wymienia wartość tych dwóch zmiennych, w zasadzie, ponieważ zmienia katalogi. Wyświetla także nazwę każdego katalogu, ponieważ działa tam na stderr.
Właśnie rzuciłem na to okiem i zdecydowałem, że lepiej sobie radzę z obsługą błędów. Pominie katalog, do którego nie może cd
- i cd
wydrukuje komunikat o tym, dlaczego stderr - i break
w / niezerowy kod wyjścia, jeśli command
nie zostanie wykonany pomyślnie lub jeśli uruchomienie w command
jakiś sposób wpłynie na jego zdolność do powrotu do oryginalnego katalogu - $OLDPWD
. W takim przypadku wykonuje również cd -
ostatni - i zapisuje wynikową bieżącą nazwę katalogu roboczego do stderr.
youtube-dl
.