Attraversa tutte le sottodirectory e fai qualcosa nello script della shell Unix


17

Voglio che il mio script della shell visiti tutte le sottodirectory di una directory principale. Fai qualcosa nelle directory, invia l'output a un file di spool e passa alla directory successiva. Considerare Dir principale = / tmp Sottotraccia = ABCD (quattro sottodirectory)


2
OK, per favore, mostraci la tua sceneggiatura finora. Quale parte ti sta dando problemi?
terdon

Risposte:


22

Usa un forciclo:

for d in $(find /path/to/dir -maxdepth 1 -type d)
do
  #Do something, the directory is accessible with $d:
  echo $d
done >output_file

Cerca solo le sottodirectory della directory /path/to/dir. Si noti che il semplice esempio sopra fallirà se i nomi delle directory contengono spazi bianchi o caratteri speciali. Un approccio più sicuro è:

find /tmp -maxdepth 1 -type d -print0 |
  while IFS= read -rd '' dir; do echo "$dir"; done

O in pianura bash:

for d in /path/to/dir/*; do
  if [ -d "$d" ]; then
    echo "$d"
  fi
done

(nota che contrariamente a findquello si considerano anche collegamenti simbolici alle directory ed esclude quelle nascoste)


1
almeno indicare i limiti e i rischi associati all'elaborazione dell'output di findsimile.
Stéphane Chazelas,

Ciao ... ho provato a correre sotto per loop per d in $ (find / backup / ASHISH -maxdepth 1 -type d) do ls -l | awk '{print $ 9}' | grep CC * _ date +"%m%d20%Y"| xargs echo echo $ d
Ashish,

Ciao ... Ho provato di seguito per loop. per d in $ (trova / backup / ASHISH -maxdepth 1 -tipo d) do ls -l | awk '{print $ 9}' | grep CC * _ date +"%m%d20%Y"| xargs echo echo $ d Il risultato atteso è ls -ltr da tutta la sottodirectory . Il ciclo sopra non funziona
Ashish,

1

Sono un bashprincipiante completo , ma un veterano delle Nazioni Unite * X. Anche se senza dubbio questo può essere fatto con gli script della shell Bash, ai vecchi tempi ci eravamo abituati find [-maxdepth <levels>] <start-dir> -exec <command> ;. Potresti fare un man findgioco e giocarci, forse fino a quando qualcuno non ti dirà come farlo bash!


Sono molto lusingato che la mia risposta "di profilo" qui abbia ricevuto un voto positivo. Tuttavia, perché la risposta di @chaos di seguito ha ricevuto un voto negativo? (Come nuovo arrivato in questo forum, non posso pubblicare questo commento contro la sua risposta, solo contro la mia.) Il suo secondo suggerimento è corretto per una soluzione di script di shell ed evita il sovraccarico di eseguire un findcomando esterno .
JonBrave,

Il suo secondo è davvero corretto. Il suo primo errore avrà esito negativo se i nomi delle directory contengono spazi bianchi o caratteri speciali (ad esempio barre rovesciate). Vedi la modifica che ho apportato alla sua risposta per la versione sicura.
terdon

Sono d'accordo. Era la sua seconda, unica risposta alla shell che stavo lodando.
JonBrave,

Lo so, stavo solo spiegando il downvote (che non ho lanciato).
terdon


1

Sembra che tu voglia i nomi dei file sotto ciascuno dei sottodir; il ls -l | awknon è abbastanza robusto, per quello che se quei nomi di file comprendono spazi bianchi e / o ritorni a capo? Quanto sotto findfunzionerebbe anche per findi casi in cui non è il caso -maxdepthper loro:

find . ! -name . -type d -prune -exec sh -c '
   cd "$1" && \
   find "." ! -name . -prune  -type f
' {} {} \;

0

Ho la soluzione. Il comando find di seguito soddisfa i miei requisiti.

find . -maxdepth 1 -type d \( ! -name . \) -exec bash -c "cd '{}' && ls -l |awk '{ print $9 }' |grep `date +"%m%d%Y"`|xargs echo" \;

0

È anche possibile usare ls, grep e tr

for dir in $(ls -1FA | grep / | tr -d /); do echo $dir/something; done

ls -1FA | grep / | tr -d / | while IFS= read -r TD; do echo $TD/something; done

du / sed può anche essere usato come selettore se il tuo ls non ha le opzioni di cui sopra

du --max-depth=1 | sed -e 's/^.*\.\///' | grep -v '\.$'

Potrebbe essere importante notare che questi esempi restituiscono directory nascoste ed escludono le directory principali e quelle correnti


1
(1)  lsscrive un file per riga (cosa -1specifica l' opzione) per impostazione predefinita quando l'output standard è una pipe (quindi è superfluo nelle risposte). (2) Analizzare l'output di lsè una cattiva idea - vedi questo e questo . La tua prima risposta fallirà se le directory hanno spazi (o newline) nei loro nomi e tutte falliranno se hanno newline nei loro nomi. (3) Dovresti sempre citare le variabili della shell (ad es. "$dir") A meno che tu non abbia una buona ragione per non farlo e sei sicuro di sapere cosa stai facendo.
Scott,

Aspetti positivi Scott. Lasciando la risposta come, per molti sistemi senza dirs egregiamente chiamati, penso che possa essere ancora utile per gli unici.
JGurtz,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.