Die Ausgabe von ls
zu verwenden, um Dateinamen zu erhalten, ist eine schlechte Idee . Es kann zu Fehlfunktionen und sogar zu gefährlichen Skripten führen. Das liegt daran, dass ein Dateiname jedes beliebige Zeichen außer /
und dem Zeichen null
enthalten kann, und ls
verwendet keines dieser Zeichen als Trennzeichen. Wenn ein Dateiname also ein Leerzeichen oder einen Zeilenumbruch enthält, werden Sie unerwartete Ergebnisse erhalten.
Es gibt zwei sehr gute Möglichkeiten, über Dateien zu iterieren. Hier habe ich einfach echo
verwendet, um zu demonstrieren, wie man etwas mit dem Dateinamen macht; man kann aber alles verwenden.
Die erste ist, die nativen Globbing-Funktionen der Shell zu verwenden.
for dir in */; do
echo "$dir"
done
Die Shell erweitert */
in separate Argumente, die die for
-Schleife liest; selbst wenn der Dateiname ein Leerzeichen, einen Zeilenumbruch oder ein anderes seltsames Zeichen enthält, sieht for
jeden vollständigen Namen als atomare Einheit; die Liste wird in keiner Weise geparst.
Wenn Sie rekursiv in Unterverzeichnisse gehen wollen, dann geht das nicht, es sei denn, Ihre Shell hat einige erweiterte Globbing-Funktionen (wie bash
‘s globstar
. Wenn Ihre Shell nicht über diese Funktionen verfügt oder wenn Sie sicherstellen wollen, dass Ihr Skript auf einer Vielzahl von Systemen funktioniert, dann ist die nächste Option die Verwendung von find
.
find . -type d -exec echo '{}' \;
Hier wird der Befehl find
echo
aufrufen und ihm ein Argument des Dateinamens übergeben. Er tut dies einmal für jede Datei, die er findet. Wie im vorigen Beispiel gibt es kein Parsen einer Liste von Dateinamen; stattdessen wird ein Dateiname vollständig als Argument gesendet.
Die Syntax des Arguments -exec
sieht ein wenig komisch aus. find
nimmt das erste Argument nach -exec
und behandelt es als das auszuführende Programm, und jedes weitere Argument wird als Argument an dieses Programm übergeben. Es gibt zwei spezielle Argumente, die -exec
sehen muss. Das erste ist {}
; dieses Argument wird durch einen Dateinamen ersetzt, den die vorherigen Teile von find
erzeugen. Das zweite ist ;
, das find
wissen lässt, dass dies das Ende der Liste der an das Programm zu übergebenden Argumente ist; find
braucht dies, weil Sie mit weiteren Argumenten fortfahren können, die für find
und nicht für das ausgeführte Programm bestimmt sind. Der Grund für [ Die Ausgabe von
lszu verwenden, um Dateinamen zu erhalten, ist eine schlechte Idee ]&003. Es kann zu Fehlfunktionen und sogar zu gefährlichen Skripten führen. Das liegt daran, dass ein Dateiname jedes beliebige Zeichen außer
/und dem Zeichen
nullenthalten kann, und
ls` verwendet keines dieser Zeichen als Trennzeichen. Wenn ein Dateiname also ein Leerzeichen oder einen Zeilenumbruch enthält, werden Sie unerwartete Ergebnisse erhalten.
Es gibt zwei sehr gute Möglichkeiten, über Dateien zu iterieren. Hier habe ich einfach echo
verwendet, um zu demonstrieren, wie man etwas mit dem Dateinamen macht; man kann aber alles verwenden.
Die erste ist, die nativen Globbing-Funktionen der Shell zu verwenden.
for dir in */; do
echo "$dir"
done
Die Shell erweitert */
in separate Argumente, die die for
-Schleife liest; selbst wenn der Dateiname ein Leerzeichen, einen Zeilenumbruch oder ein anderes seltsames Zeichen enthält, sieht for
jeden vollständigen Namen als atomare Einheit; die Liste wird in keiner Weise geparst.
Wenn Sie rekursiv in Unterverzeichnisse gehen wollen, dann geht das nicht, es sei denn, Ihre Shell hat einige erweiterte Globbing-Funktionen (wie bash
’s globstar
. Wenn Ihre Shell nicht über diese Funktionen verfügt oder wenn Sie sicherstellen wollen, dass Ihr Skript auf einer Vielzahl von Systemen funktioniert, dann ist die nächste Option die Verwendung von find
.
find . -type d -exec echo '{}' \;
Hier wird der Befehl find
echo
aufrufen und ihm ein Argument des Dateinamens übergeben. Er tut dies einmal für jede Datei, die er findet. Wie im vorigen Beispiel gibt es kein Parsen einer Liste von Dateinamen; stattdessen wird ein Dateiname vollständig als Argument gesendet.
Die Syntax des Arguments -exec
sieht ein wenig komisch aus. find
nimmt das erste Argument nach -exec
und behandelt es als das auszuführende Programm, und jedes weitere Argument wird als Argument an dieses Programm übergeben. Es gibt zwei spezielle Argumente, die -exec
sehen muss. Das erste ist {}
; dieses Argument wird durch einen Dateinamen ersetzt, den die vorherigen Teile von find
erzeugen. Das zweite ist ;
, das find
wissen lässt, dass dies das Ende der Liste der an das Programm zu übergebenden Argumente ist; find
braucht dies, weil Sie mit weiteren Argumenten fortfahren können, die für find
und nicht für das ausgeführte Programm bestimmt sind. Der Grund für ist, dass die Shell auch ;
speziell behandelt - es stellt das Ende eines Befehls dar, also müssen wir ihm entkommen, damit die Shell es als Argument an find
übergibt, anstatt es für sich selbst zu verbrauchen; eine andere Möglichkeit, die Shell dazu zu bringen, es nicht speziell zu behandeln, besteht darin, es in Anführungszeichen zu setzen: ';'
funktioniert für diesen Zweck genauso gut wie \;
.