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

Hat jemand ein Template-Shell-Skript, um etwas mit ls für eine Liste von Verzeichnisnamen zu tun und jede zu durchlaufen und etwas zu tun?

Ich plane ls -1d */, um die Liste der Verzeichnisnamen abzurufen.

Author: Daniel A. White, 2009-08-28

9 answers

Bearbeitet, um ls nicht zu verwenden, wo ein glob tun würde, wie @shawn-j-goff und andere vorgeschlagen haben.

Benutze einfach eine for..do..done Schleife:

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

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

Innerhalb der Schleife do beziehen Sie sich nur auf die Schleifenvariable mit dem Dollarzeichen-Präfix (also $f oben Beispiel). Sie können es echo oder etwas anderes tun, was Sie wollen.

Zum Beispiel, um alle .xml Dateien im aktuellen Verzeichnis in .txt umzubenennen:

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
 142
Author: Gene Gotimer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2015-05-08 00:00:06

Die Verwendung der Ausgabe von ls zum Abrufen von Dateinamen ist eine schlechte Idee. Es kann zu Fehlfunktionen und sogar gefährlichen Skripten führen. Dies ist, weil ein Dateiname kann beliebige Zeichen enthalten, außer / und nullCharakter, und ls nicht verwenden Sie eines dieser Zeichen als Begrenzungszeichen, so dass, wenn ein Dateiname ein Leerzeichen oder ein Zeilenumbruch ist, die Sie wird unerwartete Ergebnisse erhalten.

Es gibt zwei sehr gute Möglichkeiten, Dateien zu durchlaufen. Hier habe ich einfach echo verwendet, um dies zu demonstrieren etwas mit dem Dateinamen; Sie können jedoch alles verwenden.

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

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

Die Shell erweitert */ in separate Argumente, die die Schleife for liest; Selbst wenn es ein Leerzeichen, einen Zeilenumbruch oder ein anderes seltsames Zeichen im Dateinamen gibt, sieht for jeden vollständigen Namen als atomare Einheit; Es analysiert die Liste in keiner Weise.

Wenn Sie rekursiv in Unterverzeichnisse gehen wollen, dann wird dies nicht tun, wenn Ihre shell hat einige erweiterte globbing-Funktionen (wie bash's globstar. Wenn Ihre Shell nicht über diese Funktionen verfügt oder Sie sicherstellen möchten, dass Ihr Skript auf einer Vielzahl von Systemen funktioniert, verwenden Sie als Nächstes find.

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

Hier ruft der Befehl find echo auf und übergibt ihm ein Argument des Dateinamens. Es tut dies einmal für jede Datei, die es findet. Wie im vorherigen Beispiel gibt es kein Parsen einer Liste von Dateinamen; Stattdessen wird ein Dateiname vollständig als Argument.

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 nachfolgende Argument wird als Argument an dieses Programm übergeben. Es gibt zwei spezielle Argumente, die -exec sehen muss. Der erste ist {}; Dieses Argument wird durch einen Dateinamen ersetzt, den die vorherigen Teile von find erzeugen. Der zweite ist ;, wodurch find wissen kann, dass dies das Ende der Liste von argumente, die an das Programm übergeben werden sollen; find benötigt dies, da Sie mit weiteren Argumenten fortfahren können, die für find und nicht für das exec ' d-Programm bestimmt sind. Der Grund für das \ ist, dass die Shell auch ; speziell behandelt - es stellt das Ende eines Befehls dar, also müssen wir es entkommen, damit die Shell es als Argument für find gibt, anstatt es für sich selbst zu konsumieren; Eine andere Möglichkeit, die Shell dazu zu bringen, es nicht speziell zu behandeln, besteht darin, es in Anführungszeichen zu setzen: ';' funktioniert genauso sowie \; für diesen Zweck.

 74
Author: Shawn J. Goff,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2014-07-23 13:00:46

Für Dateien mit Leerzeichen müssen Sie sicherstellen, dass die Variable wie folgt zitiert wird:

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

Oder Sie können die Umgebungsvariable Input Field Separator (IFS) ändern:

 IFS=$'\n';for file in $(ls); do echo $i; done

Schließlich benötigen Sie je nachdem, was Sie tun, möglicherweise nicht einmal die ls:

 for i in *; do echo "$i"; done;
 23
Author: john,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2009-08-28 17:26:27

Wenn Sie GNU Parallel haben http://www.gnu.org/software/parallel/ installiert Sie können dies tun:

ls | parallel echo {} is in this dir

Um alle umzubenennen .txt zu .xml:

ls *.txt | parallel mv {} {.}.xml

Sehen Sie sich das Intro-Video für GNU Parallel an, um mehr zu erfahren: http://www.youtube.com/watch?v=OpaiGYxkSuQ

 4
Author: Ole Tange,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2012-04-30 00:49:30

Nur um die Antwort von CoverosGene hinzuzufügen, hier ist eine Möglichkeit, nur die Verzeichnisnamen aufzulisten:

for f in */; do
  echo "Directory -> $f"
done
 4
Author: n3o,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2015-02-11 14:36:01

Warum nicht IFS auf eine neue Zeile setzen und dann die Ausgabe von ls in einem Array erfassen? Wenn Sie IFS auf Newline setzen, sollten Probleme mit lustigen Zeichen in Dateinamen behoben werden; Die Verwendung von ls kann hilfreich sein, da es über eine integrierte Sortierfunktion verfügt.

(Beim Testen hatte ich Probleme, IFS auf \n zu setzen, aber das Setzen auf Newline Backspace funktioniert, wie an anderer Stelle hier vorgeschlagen):

ZB (vorausgesetzt, das gewünschte ls Suchmuster wurde übergeben $1):

SAVEIFS=$IFS
IFS=$(echo -en "\n\b")

FILES=($(/bin/ls "$1"))

for AFILE in ${FILES[@]}
do
    ... do something with a file ...
done

IFS=$SAVEIFS

Dies ist besonders praktisch unter OS X, um beispielsweise eine Liste von Dateien zu erfassen, die nach Erstellungsdatum sortiert sind (älteste bis neueste), lautet der Befehl ls ls -t -U -r.

 1
Author: jetset,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2012-10-22 01:09:13

While Schleife mit ls Befehl in einer Befehlszeile


ls | while read filename;do echo "file name is $filename"; done
 0
Author: dılo sürücü,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2020-10-06 22:05:14

Es ist präfektlich in Ordnung:

#!/bin/sh
for i in `ls`
do
   echo `ls -l $i`
done

Hier ist die Ausgabe:

root@online:/usr/local/httpd/bin # more ~root/rm-in-ls.sh
    #!/bin/sh
    for i in `ls` 
    do
      echo `ls -l $i`
    done

root@online:/usr/local/httpd/bin # /root/rm-in-ls.sh
-rwxr-xr-x 1 root wheel 82516 Jul 3 04:52 ab
-rwxr-xr-x 1 root 40 3431 Jul 3 04:35 apachectl
-rwxr-xr-x 1 root 40 23881 Jul 3 04:35 apxs
-rwxr-xr-x 1 root wheel 21456 Jul 3 04:52 checkgid
-rwxr-xr-x 1 root 40 8931 Jul 3 04:35 dbmmanage
root@online:/usr/local/httpd/bin # 

Verpasst ! Richtig !!!

- HEADS UP !!!

Das ist nicht "'" in 'ls' !!! Das ist " ` " in `ls`. Der akute nicht apostroph. Es gibt einen Unterschied zwischen ' und `. Ich verbrachte eine Woche damit, um herauszufinden, wann ich auf dem College war (1990).

Dies ist "`", die Taste mit ~ Tilde + shift+~, sie heißt akut.wiki

Wenn Sie es nicht erhalten haben, kopieren und fügen Sie das Skript ein und führen Sie es aus.

 -2
Author: Biddut Mitra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2020-07-14 23:30:01

So mache ich es, aber es gibt wahrscheinlich effizientere Wege.

ls > filelist.txt

while read filename; do echo filename: "$filename"; done < filelist.txt
 -3
Author: TREE,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/techietown.info/template/agent.layouts/content.php on line 61
2009-08-28 17:28:24