Wykonaj akcję w każdym podkatalogu używając Bash

Pracuję nad skryptem, który musi wykonać akcję w każdym podkatalogu określonego folderu.

Jaki jest najskuteczniejszy sposób na napisanie tego?

Author: jww, 2010-10-22

9 answers

for D in `find . -type d`
do
    //Do whatever you need with D
done
 186
Author: Mike Clark,
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
2014-01-07 16:41:19

Wersja, która unika tworzenia pod-procesu:

for D in *; do
    if [ -d "${D}" ]; then
        echo "${D}"   # your processing here
    fi
done

Lub, jeśli akcja jest pojedynczym poleceniem, jest to bardziej zwięzłe:

for D in *; do [ -d "${D}" ] && my_command; done

Lub jeszcze bardziej zwięzła wersja (dzięki @ enzotib ). Zauważ, że w tej wersji każda wartość D będzie miała końcowy ukośnik:

for D in */; do my_command; done
 301
Author: kanaka,
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 12:18:20

Najprostszym nie rekurencyjnym sposobem jest:

for d in */; do
    echo "$d"
done

/ na końcu mówi, używać tylko katalogów.

Nie ma potrzeby

  • znajdź
  • awk
  • ...
 117
Author: d0x,
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-11-14 08:35:37

Użyj polecenia find.

W GNU find możesz użyć parametru -execdir:

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

Lub używając parametru -exec:

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

Lub z xargs poleceniem:

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

Lub używając dla pętli:

for d in */; { echo "$d"; }

dla rekurencyjności spróbuj zamiast tego rozszerzonego globbingu (**/) (enable by: shopt -s extglob).


Aby uzyskać więcej przykładów, zobacz: Jak przejść do każdego katalogu i wykonać polecenie? W SO

 20
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 10:31:33

Handy one-liners

for D in *; do echo "$D"; done
for D in *; do find "$D" -type d; done ### Option A

find * -type d ### Option B

Opcja A jest prawidłowa dla folderów ze spacjami pomiędzy. Ponadto, ogólnie szybciej, ponieważ nie drukuje każdego słowa w nazwie folderu jako osobnego elementu.

# Option A
$ time for D in ./big_dir/*; do find "$D" -type d > /dev/null; done
real    0m0.327s
user    0m0.084s
sys     0m0.236s

# Option B
$ time for D in `find ./big_dir/* -type d`; do echo "$D" > /dev/null; done
real    0m0.787s
user    0m0.484s
sys     0m0.308s
 13
Author: Sriram Murali,
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-10-12 20:58:00

find . -type d -print0 | xargs -0 -n 1 my_command

 10
Author: Paul Tomblin,
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
2010-10-22 20:18:21

Spowoduje to utworzenie subshell (co oznacza, że wartości zmiennych zostaną utracone po zakończeniu pętli while):

find . -type d | while read -r dir
do
    something
done

To nie będzie:

while read -r dir
do
    something
done < <(find . -type d)

Każda z nich będzie działać, jeśli w nazwach katalogów są spacje.

 7
Author: Dennis Williamson,
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
2010-10-23 00:26:21

Możesz spróbować:

#!/bin/bash
### $1 == the first args to this script
### usage: script.sh /path/to/dir/

for f in `find . -maxdepth 1 -mindepth 1 -type d`; do
  cd "$f"
  <your job here>
done

Lub podobne...

Wyjaśnienie:

find . -maxdepth 1 -mindepth 1 -type d : Znajdź tylko katalogi o maksymalnej głębokości rekurencyjnej 1 (tylko podkatalogi $1) i minimalnej głębokości 1 (nie obejmuje bieżącego folderu .)

 6
Author: Henry Dobson,
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-07-25 06:26:00

Akceptowana odpowiedź będzie łamana na białych spacjach, jeśli nazwy katalogów je zawierają, A preferowaną składnią jest $() dla bash / ksh. Użycie GNU find -exec opcja z +; eg

find .... -exec mycommand +; #this is same as passing to xargs

Lub użyj pętli while

find .... |  while read -r D
do
  ...
done 
 5
Author: ghostdog74,
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
2010-10-22 23:24:11