it-swarm.com.de

Wie kann man Verzeichnisse unter Linux durchlaufen?

Ich schreibe ein Skript in Bash unter Linux und muss alle Unterverzeichnisnamen in einem bestimmten Verzeichnis durchgehen. Wie kann ich diese Verzeichnisse durchlaufen (und normale Dateien überspringen)?

Zum Beispiel:
Das angegebene Verzeichnis ist /tmp/
Es hat die folgenden Unterverzeichnisse: /tmp/A, /tmp/B, /tmp/C

Ich möchte A, B, C abrufen.

143
Erik Sapir
cd /tmp
find . -maxdepth 1 -mindepth 1 -type d -printf '%f\n'

Eine kurze Erklärung: find findet Dateien (ganz offensichtlich)

  • . ist das aktuelle Verzeichnis, nach der CD ist es /tmp (IMHO ist dies flexibler als mit /tmp direkt im find Befehl. Sie haben nur einen Ort, den cd, zu ändern, wenn in diesem Ordner weitere Aktionen stattfinden sollen.)

  • -maxdepth 1 und -mindepth 1 stellen Sie sicher, dass find wirklich nur in das aktuelle Verzeichnis schaut und nicht '.' im Ergebnis

  • -type d sucht nur nach Verzeichnissen

  • -printf '%f\n druckt nur den Namen des gefundenen Ordners (plus eine neue Zeile) für jeden Treffer.

E voila!

119
Boldewyn

Für alle bisherigen Antworten wird find verwendet. Hier ist also nur eine mit der Shell. In Ihrem Fall sind keine externen Werkzeuge erforderlich:

for dir in /tmp/*/     # list directories in the form "/tmp/dirname/"
do
    dir=${dir%*/}      # remove the trailing "/"
    echo ${dir##*/}    # print everything after the final "/"
done
403
ghostdog74

Sie können alle Verzeichnisse einschließlich versteckter Verzeichnisse (beginnend mit einem Punkt) durchlaufen mit:

for file in */ .*/ ; do echo "$file is a directory"; done

anmerkung: nter Verwendung der Liste */ .*/ funktioniert in zsh nur, wenn der Ordner mindestens ein verstecktes Verzeichnis enthält. In der Bash wird auch . und ..


Eine andere Möglichkeit für bash, versteckte Verzeichnisse einzuschließen, wäre:

shopt -s dotglob;
for file in */ ; do echo "$file is a directory"; done

Wenn Sie Symlinks ausschließen möchten:

for file in */ ; do 
  if [[ -d "$file" && ! -L "$file" ]]; then
    echo "$file is a directory"; 
  fi; 
done

Um in jeder Lösung nur den Namen des nachfolgenden Verzeichnisses (A, B, C wie abgefragt) auszugeben, verwenden Sie dies in den Schleifen:

file="${file%/}"     # strip trailing slash
file="${file##*/}"   # strip path and leading slash
echo "$file is the directoryname without slashes"

Beispiel (dies funktioniert auch mit Verzeichnissen, die Leerzeichen enthalten):

mkdir /tmp/A /tmp/B /tmp/C "/tmp/ dir with spaces"
for file in /tmp/*/ ; do file="${file%/}"; echo "${file##*/}"; done
39
rubo77

Funktioniert mit Verzeichnissen, die Leerzeichen enthalten

Inspiriert von Sorpigal

while IFS= read -d $'\0' -r file ; do 
    echo $file; ls $file ; 
done < <(find /path/to/dir/ -mindepth 1 -maxdepth 1 -type d -print0)

Originalbeitrag (Funktioniert nicht mit Leerzeichen)

Inspiriert von Boldewyn : Beispiel einer Schleife mit dem Befehl find.

for D in $(find /path/to/dir/ -mindepth 1 -maxdepth 1 -type d) ; do
    echo $D ;
done
15
zpon
find . -mindepth 1 -maxdepth 1 -type d -printf "%P\n"

Die Technik, die ich am häufigsten benutze, ist find | xargs. Wenn Sie beispielsweise jede Datei in diesem Verzeichnis und allen seinen Unterverzeichnissen für die Welt lesbar machen möchten, können Sie Folgendes tun:

find . -type f -print0 | xargs -0 chmod go+r
find . -type d -print0 | xargs -0 chmod go+rx

Die Option -print0 Endet mit einem NULL-Zeichen anstelle eines Leerzeichens. Die Option -0 Teilt die Eingabe auf die gleiche Weise. Das ist also die Kombination für Dateien mit Leerzeichen.

Sie können sich diese Befehlskette so vorstellen, als würden Sie jede ausgegebene Zeile von find nehmen und an das Ende eines chmod Befehls kleben.

Wenn Sie den Befehl als Argument in der Mitte anstatt am Ende ausführen möchten, müssen Sie ein bisschen kreativ sein. Ich musste zum Beispiel in jedes Unterverzeichnis wechseln und den Befehl latemk -c Ausführen. Also habe ich (von Wikipedia ) verwendet:

find . -type d -depth 1 -print0 | \
    xargs -0 sh -c 'for dir; do pushd "$dir" && latexmk -c && popd; done' fnord

Dies hat die Wirkung von for dir $(subdirs); do stuff; done, ist jedoch für Verzeichnisse mit Leerzeichen im Namen sicher. Außerdem werden die einzelnen Aufrufe von stuff in derselben Shell ausgeführt, weshalb wir in meinem Befehl mit popd zum aktuellen Verzeichnis zurückkehren müssen.

5

find . -type d -maxdepth 1

2
Anonymous

eine minimale Bash-Schleife, aus der Sie bauen können (basierend auf ghostdog74 answer)

for dir in directory/*                                                     
do                                                                                 
  echo ${dir}                                                                  
done

eine ganze Reihe von Dateien nach Verzeichnis zu komprimieren

for dir in directory/*
do
  Zip -r ${dir##*/} ${dir}
done                                               
2
Harry Moreno