Jak przejść do każdego katalogu i wykonać polecenie?
Jak napisać skrypt bash, który przechodzi przez każdy katalog wewnątrz parent_directory i wykonuje A polecenie w każdy katalog .
Struktura katalogów jest następująca:
Parent_directory (nazwa może być dowolna - nie podąża za wzorcem)
- 001 (nazwy katalogów podążają za tym wzorcem)
- 0001.txt (nazwy plików podążają za tym wzorcem)
- 0002.txt
- 0003.txt
- 002
- 0001.txt
- 0002.txt
- 0003.txt
- 0004.txt
- 003
- 0001.txt
Liczba katalogów jest nieznana.
9 answers
Możesz wykonać następujące czynności, gdy Twoim bieżącym katalogiem jest parent_directory
:
for d in [0-9][0-9][0-9]
do
( cd $d && your-command-here )
done
(
i )
tworzą subshell, aby bieżący katalog nie został zmieniony w skrypcie głównym.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-19 11:42:00
This answer posted by Todd help me.
find . -maxdepth 1 -type d \( ! -name . \) -exec bash -c "cd '{}' && pwd" \;
\( ! -name . \)
unika wykonywania polecenia w bieżącym katalogu.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-13 12:22:45
Jeśli używasz GNU find
, Możesz spróbować parametru -execdir
, np.:
find . -type d -execdir realpath "{}" ';'
Lub (zgodnie z @gniourf_gniourf komentarz):
find . -type d -execdir sh -c 'printf "%s/%s\n" "$PWD" "$0"' {} \;
Uwaga: możesz użyć ${0#./}
zamiast $0
, aby naprawić ./
z przodu.
Lub bardziej praktyczny przykład:
find . -name .git -type d -execdir git pull -v ';'
Jeśli chcesz dołączyć bieżący katalog, jest to jeszcze prostsze, używając -exec
:
find . -type d -exec sh -c 'cd -P -- "{}" && pwd -P' \;
Lub używając xargs
:
find . -type d -print0 | xargs -0 -L1 sh -c 'cd "$0" && pwd && echo Do stuff'
Lub podobny przykład sugerowany przez @gniourf_gniourf :
find . -type d -print0 | while IFS= read -r -d '' file; do
# ...
done
powyższe przykłady obsługują katalogi ze spacjami w nazwie.
Lub poprzez przypisanie do tablicy bash:
dirs=($(find . -type d))
for dir in "${dirs[@]}"; do
cd "$dir"
echo $PWD
done
Zmień .
na konkretną nazwę folderu. Jeśli nie musisz uruchamiać rekurencyjnie, możesz użyć: dirs=(*)
. Powyższy przykład nie obsługuje katalogów ze spacjami w nazwie.
Tak jak @gniourf_gniourf zasugerował, jedynym właściwym sposobem, aby umieścić wyjście z Znajdź w tablicy bez użycia jawnej pętli będzie dostępne w Bash 4.4 z:
mapfile -t -d '' dirs < <(find . -type d -print0)
Lub nie zalecany sposób (który obejmuje parsowanie ls
):
ls -d */ | awk '{print $NF}' | xargs -n1 sh -c 'cd $0 && pwd && echo Do stuff'
powyższy przykład zignoruje bieżący katalog (zgodnie z życzeniem OP), ale spowoduje złamanie nazw ze spacjami.
Zobacz też:
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:54:54
Jeśli folder toplevel jest znany, możesz napisać coś takiego:
for dir in `ls $YOUR_TOP_LEVEL_FOLDER`;
do
for subdir in `ls $YOUR_TOP_LEVEL_FOLDER/$dir`;
do
$(PLAY AS MUCH AS YOU WANT);
done
done
Na $(Graj ile chcesz); możesz umieścić tyle kodu, ile chcesz.
Zauważ, że nie " cd " w żadnym katalogu.
Zdrówko, zdrówko]}Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-19 11:29:26
for dir in PARENT/*
do
test -d "$dir" || continue
# Do something with $dir...
done
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-21 08:26:20
Podczas gdy jeden Liner jest dobry do szybkiego i brudnego użytkowania, wolę poniżej bardziej wyrazistą wersję do pisania skryptów. Jest to szablon, którego używam, który zajmuje się wieloma przypadkami brzegowymi i pozwala pisać bardziej złożony kod do wykonania na folderze. Możesz napisać swój kod bash w funkcji dir_command. Poniżej, dir_coomand implementuje tagowanie każdego repozytorium w git jako przykład. Reszta skryptu wywołuje dir_command dla każdego folderu w katalogu. Przykład iteracji przez tylko podany zbiór folder jest również dołączony.
#!/bin/bash
#Use set -x if you want to echo each command while getting executed
#set -x
#Save current directory so we can restore it later
cur=$PWD
#Save command line arguments so functions can access it
args=("$@")
#Put your code in this function
#To access command line arguments use syntax ${args[1]} etc
function dir_command {
#This example command implements doing git status for folder
cd $1
echo "$(tput setaf 2)$1$(tput sgr 0)"
git tag -a ${args[0]} -m "${args[1]}"
git push --tags
cd ..
}
#This loop will go to each immediate child and execute dir_command
find . -maxdepth 1 -type d \( ! -name . \) | while read dir; do
dir_command "$dir/"
done
#This example loop only loops through give set of folders
declare -a dirs=("dir1" "dir2" "dir3")
for dir in "${dirs[@]}"; do
dir_command "$dir/"
done
#Restore the folder
cd "$cur"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-02 04:24:43
Nie rozumiem sensu formatowania pliku, ponieważ chcesz tylko iterację przez foldery... Szukasz czegoś takiego?
cd parent
find . -type d | while read d; do
ls $d/
done
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-19 11:28:36
Możesz użyć
find .
Aby przeszukać wszystkie pliki / dirs w bieżącym katalogu recurive
Niż można przesłać wyjście polecenia xargs w ten sposób
find . | xargs 'command here'
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-19 11:29:01
for p in [0-9][0-9][0-9];do
(
cd $p
for f in [0-9][0-9][0-9][0-9]*.txt;do
ls $f; # Your operands
done
)
done
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-17 11:58:59