Iterieren über jede Zeile der ls-l-Ausgabe

119

Ich möchte über jede Zeile in der Ausgabe von: iterieren. ls -l /some/dir/*

Im Moment versuche ich: for x in $(ls -l $1); do echo $x; done

Dies iteriert jedoch über jedes Element in der Zeile separat, sodass ich Folgendes erhalte:

-r--r-----
1
ivanevf
eng
1074
Apr
22
13:07
File1

-r--r-----
1
ivanevf
eng
1074
Apr
22
13:17
File2

Ich möchte jedoch jede Zeile als Ganzes durchlaufen. Wie mache ich das?

Ivan
quelle
1
Zitieren Sie immer Variablen (und die Befehlsausgabe), es sei denn, Sie haben einen bestimmten Grund, dies nicht zu tun.
Glenn Jackman

Antworten:

246

Stellen Sie IFS wie folgt auf newline ein:

IFS='
'
for x in `ls -l $1`; do echo $x; done

Legen Sie eine Sub-Shell darum, wenn Sie IFS nicht dauerhaft festlegen möchten:

(IFS='
'
for x in `ls -l $1`; do echo $x; done)

Oder verwenden Sie while | Lesen Sie stattdessen:

ls -l $1 | while read x; do echo $x; done

Eine weitere Option, mit der while / read auf derselben Shell-Ebene ausgeführt wird:

while read x; do echo $x; done << EOF
$(ls -l $1)
EOF
Randy Proctor
quelle
12
Vorsicht beim Piping zu while, das while wird in einer Subshell ausgeführt, was bedeutet, dass Variablen im Hauptprozess nicht geändert werden konnten
Reorx
1
Was macht der $ 1 hier? Ich muss dies in einem Skript verwenden, das ich schreibe und das Argumente akzeptiert. Der $ 1 wirft die Dinge ab. Was kann ich dort anstelle von 1 US-Dollar setzen, um den gleichen Effekt zu erzielen? Ich möchte die zweite Lösung verwenden.
Noob-in-Need
@ Noob-in-Need Ersetzen Sie es durch das Verzeichnis, das Sie
auflisten
1
Möglicherweise möchten Sie dies tun, read -roder Bash entfernt nicht entkoppelte Backslashes aus den Daten.
Brian Gordon
6

Es hängt davon ab, was Sie mit jeder Zeile tun möchten. awk ist ein nützliches Dienstprogramm für diese Art der Verarbeitung. Beispiel:

 ls -l | awk '{print $9, $5}'

.. druckt auf meinem System den Namen und die Größe jedes Elements im Verzeichnis.

Adam Holmberg
quelle
3

Wie bereits erwähnt, ist awk das richtige Werkzeug dafür. Wenn Sie awk nicht verwenden möchten, anstatt die Ausgabe von "ls -l" Zeile für Zeile zu analysieren, können Sie alle Dateien durchlaufen und für jede einzelne Datei ein "ls -l" wie folgt ausführen:

for x in * ; do echo `ls -ld $x` ; done
Axel
quelle
3

Sie können den findBefehl auch ausprobieren . Wenn Sie nur Dateien im aktuellen Verzeichnis möchten:

find . -d 1 -prune -ls

Führen Sie einen Befehl für jeden von ihnen aus?

find . -d 1 -prune -exec echo {} \;

Zeilen zählen, aber nur in Dateien?

find . -d 1 -prune -type f -exec wc -l {} \;

David Koski
quelle
Fund ist kaputt. Oft bekomme ich einige bizarre Fehlermeldungen. Es möchte mir helfen, wenn die Befehlszeile vollkommen gültig ist, und es scheint, als würde es nach dem nächsten Neustart möglicherweise nicht aufhören, sobald es damit beginnt. In Bezug auf Fehler scheint es manchmal zufällig zu sein. Ich bin mir nicht sicher, wie ich den Fehler melden kann.
Jim Michaels
1

Das Dienstprogramm read (1) und die Ausgabeumleitung des Befehls ls (1) machen das, was Sie wollen.

Steve Emmerson
quelle
-1

Warum hat niemand vorgeschlagen, nur Optionen zu verwenden, die die Teile eliminieren, die er nicht verarbeiten möchte?

Auf dem modernen Debian erhalten Sie einfach Ihre Datei mit:

ls --format=single-column 

Außerdem müssen Sie nicht darauf achten, in welchem ​​Verzeichnis Sie es ausführen, wenn Sie das vollständige Verzeichnis verwenden:

ls --format=single-column /root/dir/starting/point/to/target/dir/

Diesen letzten Befehl verwende ich oben und erhalte die folgende Ausgabe:

bot@dev:~/downloaded/Daily# ls --format=single-column /home/bot/downloaded/Daily/*.gz
/home/bot/downloaded/Daily/Liq_DailyManifest_V3_US_20141119_IENT1.txt.gz
/home/bot/downloaded/Daily/Liq_DailyManifest_V3_US_20141120_IENT1.txt.gz
/home/bot/downloaded/Daily/Liq_DailyManifest_V3_US_20141121_IENT1.txt.gz
BradChesney79
quelle