das Durchlaufen von `ls` führt zu einem Bash-Shell-Skript

das Durchlaufen von `ls` führt zu einem Bash-Shell-Skript

Hat jemand eine Shell-Skript-Vorlage, um etwas mit lseiner Liste von Verzeichnisnamen zu tun, jeden einzelnen zu durchlaufen und etwas zu tun?

Ich habe vor, ls -1d */die Liste der Verzeichnisnamen abzurufen.

Antwort1

Bearbeitet, um kein ls zu verwenden, wo ein Glob ausreichen würde, wie @shawn-j-goff und andere vorgeschlagen haben.

Verwenden Sie einfach eine for..do..doneSchleife:

for f in *; do
  echo "File -> $f"
done

Sie können es *durch *.txtoder jeden anderen Glob ersetzen, der eine Liste (von Dateien, Verzeichnissen oder was auch immer) zurückgibt, einen Befehl, der eine Liste generiert, z. B. $(cat filelist.txt), oder es tatsächlich durch eine Liste ersetzen.

Innerhalb der doSchleife verweisen Sie einfach mit dem Dollarzeichen als Präfix auf die Schleifenvariable (so $fim obigen Beispiel). Sie können echodamit machen, was Sie wollen.

.xmlSo können Sie beispielsweise alle Dateien im aktuellen Verzeichnis wie folgt umbenennen .txt:

for x in *.xml; do 
  t=$(echo $x | sed 's/\.xml$/.txt/'); 
  mv $x $t && echo "moved $x -> $t"
done

Oder noch besser: Wenn Sie Bash verwenden, können Sie Bash-Parametererweiterungen verwenden, anstatt eine Subshell zu erzeugen:

for x in *.xml; do 
  t=${x%.xml}.txt
  mv $x $t && echo "moved $x -> $t"
done

Antwort2

Die Ausgabe von lszum Abrufen von Dateinamen zu verwenden, ist keine gute Idee. Dies kann zu Fehlfunktionen und sogar gefährlichen Skripten führen. Dies liegt daran, dass ein Dateiname jedes beliebige Zeichen außer /und enthalten kann nullund lskeines dieser Zeichen als Trennzeichen verwendet. Wenn ein Dateiname also ein Leerzeichen oder eine neue Zeile enthält,Willeerhalten Sie unerwartete Ergebnisse.

Es gibt zwei sehr gute Möglichkeiten, über Dateien zu iterieren. Hier habe ich einfach echodemonstriert, wie man mit dem Dateinamen etwas macht; Sie können jedoch alles andere verwenden.

Die erste besteht darin, die nativen Globbing-Funktionen der Shell zu verwenden.

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

Die Shell erweitert die Datei */in einzelne Argumente, die von der forSchleife gelesen werden. Auch wenn der Dateiname ein Leerzeichen, eine neue Zeile oder ein anderes seltsames Zeichen enthält, forwird jeder vollständige Name als atomare Einheit betrachtet. Die Liste wird in keiner Weise analysiert.

Wenn Sie rekursiv in Unterverzeichnisse gehen möchten, ist dies nicht möglich, es sei denn, Ihre Shell verfügt über erweiterte Globbing-Funktionen (wie beispielsweise ) bash. globstarWenn Ihre Shell diese Funktionen nicht hat oder Sie sicherstellen möchten, dass Ihr Skript auf einer Vielzahl von Systemen funktioniert, besteht die nächste Option in der Verwendung von find.

find . -type d -exec echo '{}' \;

Hier findwird der Befehl aufgerufen echound ihm als Argument der Dateiname übergeben. Dies geschieht einmal für jede gefundene Datei. Wie im vorherigen Beispiel wird keine Liste von Dateinamen analysiert; stattdessen wird ein vollständiger Dateiname als Argument gesendet.

Die Syntax des -execArguments sieht etwas komisch aus. findnimmt das erste Argument nach -execund behandelt das als das auszuführende Programm und jedes nachfolgende Argument nimmt es als Argument, das an dieses Programm übergeben wird. Es gibt zwei spezielle Argumente, die -execgesehen werden müssen. Das erste ist {}; dieses Argument wird durch einen Dateinamen ersetzt, den die vorherigen Teile von findgeneriert haben. Das zweite ist ;, das mitteilt, dass finddies das Ende der Liste der an das Programm zu übergebenden Argumente ist; findbenötigt dies, weil Sie mit weiteren Argumenten fortfahren können, die findfür das ausgeführte Programm bestimmt sind und nicht. Der Grund dafür \ist, dass die Shell auch speziell behandelt ;– es stellt das Ende eines Befehls dar, also müssen wir es maskieren, damit die Shell es als Argument an übergibt, anstatt findes für sich selbst zu verwenden; 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 .\;

Antwort3

Bei Dateien, die Leerzeichen enthalten, müssen Sie darauf achten, die Variable wie folgt in Anführungszeichen zu setzen:

 for i in $(ls); do echo "$i"; done; 

oder Sie können die Umgebungsvariable „Eingabefeldtrennzeichen“ (IFS) ändern:

 (IFS=$'\n';for i in $(ls); do echo $i; done) # subshell to restore IFS

Abhängig davon, was Sie tun, benötigen Sie das LS möglicherweise nicht einmal:

 for i in *; do echo "$i"; done;

Antwort4

Als Ergänzung zur Antwort von CoverosGene gibt es hier eine Möglichkeit, nur die Verzeichnisnamen aufzulisten:

for f in */; do
  echo "Directory -> $f"
done

verwandte Informationen