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.

Author: Chris Maes, 2011-09-19

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.

 77
Author: Mark Longair,
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.

 101
Author: Christian Vielma,
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ż:

 31
Author: kenorb,
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]}
 17
Author: gforcada,
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
 10
Author: Idelic,
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"
 4
Author: ShitalShah,
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
 3
Author: Aif,
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'
 3
Author: Dan Bizdadea,
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
 0
Author: Fedir RYKHTIK,
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