Angenommen, mein Hauptverzeichnis ist /home/test
Darunter habe ich viele Unterverzeichnisse und unter Unterverzeichnissen noch viele davon und so weiter.
Beispiel:
/home/test
/home/test/subdir1
/home/test/subdir1/subdir2
/home/test/subdir1/subdir2/subdir3
/home/test/subdir1/subdir2/subdir4
/home/test/subdir1/subdir2/subdir4/subdir5
und so weiter ...
Ich möchte ein einfaches Skript, das jedes Verzeichnis verwendet und nur den pwd
Befehl ausführt.
shell
files
directory
directory-structure
youweek1
quelle
quelle
pwd
als Proof of Concept verwenden?pwd
ist in vielerlei Hinsicht etwas Besonderes - das ist Verwirrung, da es als Beispielbefehl verwendet wird.Antworten:
Lösung mit Parallel
Sie können GNU Parallel für eine kompakte, schnellere Lösung verwenden.
find . -type d -print0 | parallel -0 cd {}'&&' <command-name>
Dies funktioniert auch bei Verzeichnisnamen mit Leerzeichen und Zeilenumbrüchen einwandfrei. Was
parallel
hier bedeutet, ist, dass es die Ausgabe ausfind
jedem Verzeichnis nimmt und sie dann mit cd an die CD weiterleitet{}
. Wenn das Ändern des Verzeichnisses erfolgreich ist, wird unter diesem Verzeichnis ein separater Befehl ausgeführt.Regelmäßige Lösung mit while-Schleife
find "$PWD" -type d | while read -r line; do cd "$line" && <command-name>; done;
Beachten Sie, dass dies
$PWD
hier verwendet wird, da diese Variable den absoluten Pfad des aktuellen Verzeichnisses enthält, von dem aus der Befehl ausgeführt wird. Wenn Sie keinen absoluten Pfad verwenden, wirdcd
möglicherweise ein Fehler in der while-Schleife ausgegeben.Dies ist eine einfachere Lösung. Es funktioniert die meiste Zeit, außer wenn Verzeichnisnamen seltsame Zeichen wie Zeilenumbrüche enthalten (siehe Kommentare).
quelle
$PWD
oder einem Unterverzeichnisnamen.cd
erfolgreich ist oder nicht.-print0
mitfind
der Ausgabe in eindeutiger Form zu erhalten (nul-getrennt statt Newline-getrennt). Verwenden Sie für das zweite Beispiel, umread -d $'\0' -r line
die Ausgabe von zu lesenfind
. Überprüfen Sie beim ersten Mal, obparallel
eine Option vorhanden ist, die angibt, dass die Eingabe nicht durch Zeilenumbrüche getrennt werden soll. es könnte so etwas wie genannt werden-0
,-z
oder--null
. (Oder für einen anderen Ansatz siehe meine Antwort.)Der
find
Befehl ist mächtig, aber das macht es ein wenig schwierig zu benutzen.Ich bin mir ziemlich sicher, dass es das kann, was Sie brauchen - dieser Befehl unten ist "fast" das, wonach Sie fragen:
Aber - dies führt den Befehl nicht in der tiefsten Verzeichnisebene aus - er wird in den Verzeichnissen ausgeführt, in denen sich andere Verzeichnisse befinden.
Also läuft es rein
subdir4
, weil es enthältsubdir5
. Aber nicht insubdir5
- wie Sie wahrscheinlich erwarten.Es ist wichtig, dass die
-execdir
Option verwendet wird, nicht die bekanntere-exec
(sieheman find
):Die
-exec
Option führt den Befehl im Startverzeichnis aus und hat auch andere Nachteile:Aber die Option
-execdir
ist genau das, wonach Sie fragen:quelle
dir1
wird esexecdir pwd
100 - mal).Eine der anderen Antworten kam dem nahe:
(Ausführen des Befehls nur, wenn dies
cd
erfolgreich ist). Einige Leute empfehlen, ein Dummy-Argument einzufügen, damit das gefundene Verzeichnis ({}
) zu Folgendem wechselt$1
:Natürlich können Sie hier anstelle von auch eine beliebige Zeichenfolge verwenden
foo
. Gemeinsame Entscheidungen sind-
,--
undsh
. Diese Zeichenfolge wird in Fehlermeldungen (falls vorhanden) verwendet, z.so
sh
scheint eine gute Wahl zu sein.\;
und";"
sind absolut gleichwertig; Das ist nur eine Stilvorliebe.Die obigen Befehle führen die Shell für jedes Verzeichnis einmal aus. Dies kann mit Leistungseinbußen verbunden sein (insbesondere wenn der auszuführende Befehl relativ leicht ist). Alternativen sind
die die Shell einmal ausführt, aber für jedes Verzeichnis einmal gabelt, und
das bringt keine Subshells hervor. Wenn Sie einen absoluten Pfad suchen, wie Ihre Frage nahelegt, können Sie das oben Genannte kombinieren und tun
Das bringt keine Subshells hervor und muss sich auch nicht darum kümmern, den Startpunkt zu speichern.
quelle
$OLDPWD
, sodass Sie keine zusätzliche Kopie speichern müssen$save_d
. Die POSIX-Syntax zum Schleifen über "$ @" istfor d do
nichtfor d; do
(obwohl letztere ebenfalls weitgehend unterstützt wird (außer in der Bourne-Shell, die ohnehin keine POSIX-Shell ist)).cmd
es durch eine Folge von Befehlen einschließlich anderercd
Befehle ersetzt wird, ist dies$OLDPATH
nicht mehr das Verzeichnis, in dem das ausgeführtfind
wird.bash
undpdksh
basierend auf Implementierungen von sh, wenncmd
es sich um einen externen Befehl handelt,(cd "$d" && cmd)
keinen zusätzlichen Prozess (im Vergleich zu demselben ohne die Subshell) verzweigt, da ercmd
direkt im Subshell-Prozess ausgeführt wird. Es wäre also eine Schande, ihn zu vermeiden Leistungsgründe in diesen Fällen.cmd
ein einziger Befehl ist.(cd "$d" && cmd₁ && cmd₂)
würde benötigen einen zusätzlichen Prozess gabeln, wäre es nicht?Sie müssen keinen zusätzlichen
pwd
Befehl ausführen. Sie können den folgenden Befehl ausführen:Sie können Ihr Verzeichnis durch ersetzen
test/
quelle
pwd
ist in vielerlei Hinsicht etwas Besonderes - das sorgt für Verwirrung.Sie können so etwas verwenden
Beispiel:
Der folgende Befehl zeigt den Verzeichnisnamen an, ähnlich wie beim Ausführen eines pwd-Befehls.
quelle
find: missing argument to
-exec'`