Iterando su ogni riga dell'output di ls -l


119

Voglio iterare su ogni riga nell'output di: ls -l /some/dir/*

In questo momento sto provando: for x in $(ls -l $1); do echo $x; done

Tuttavia, questo itera su ogni elemento nella riga separatamente, quindi ottengo:

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

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

Ma voglio iterare su ogni riga nel suo insieme, però. Come lo faccio?


1
Cita sempre le variabili (e l'output del comando) a meno che tu non abbia un motivo specifico per non farlo.
glenn jackman

Risposte:


246

Imposta IFS su nuova riga, in questo modo:

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

Metti una sotto-shell attorno ad esso se non vuoi impostare IFS in modo permanente:

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

Oppure usa while | leggi invece:

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

Un'altra opzione, che esegue il while / read allo stesso livello di shell:

while read x; do echo $x; done << EOF
$(ls -l $1)
EOF

12
Fai attenzione quando esegui il piping a while, il while verrà eseguito in una subshell, il che significa che non può modificare le variabili nel processo principale
Reorx

1
Cosa ci fa il $ 1 qui? Ho bisogno di usarlo in uno script che sto scrivendo che accetta argomenti. Il $ 1 sta buttando via le cose. Cosa posso mettere lì invece di $ 1 per ottenere lo stesso effetto? Vorrei utilizzare la seconda soluzione.
noob-in-need

@ noob-in-need Sostituiscilo con qualsiasi directory desideri elencare
vpzomtrrfrt

1
Potresti volerlo fare read -raltrimenti bash eliminerà i backslash senza caratteri di escape dai dati.
Brian Gordon

6

Dipende da cosa vuoi fare con ogni riga. awk è un'utilità utile per questo tipo di elaborazione. Esempio:

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

.. sul mio sistema stampa il nome e la dimensione di ogni elemento nella directory.


3

Come già accennato, awk è lo strumento giusto per questo. Se non vuoi usare awk, invece di analizzare l'output di "ls -l" riga per riga, puoi iterare su tutti i file e fare un "ls -l" per ogni singolo file in questo modo:

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

3

Puoi anche provare il findcomando. Se vuoi solo i file nella directory corrente:

find . -d 1 -prune -ls

Eseguire un comando su ciascuno di essi?

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

Contare le righe, ma solo nei file?

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


trovare è rotto. Spesso ricevo alcuni messaggi di errore bizzarri. vuole aiutarmi quando la riga di comando è perfettamente valida, e sembra che una volta che inizia a farlo, non si fermerà fino al prossimo riavvio FORSE. a volte sembra di natura casuale per quanto riguarda gli errori. non sono sicuro di come posso segnalare il bug.
Jim Michaels

1

L'utilità read (1) insieme al reindirizzamento dell'output del comando ls (1) farà quello che vuoi.


-1

Quindi, perché nessuno ha suggerito di utilizzare solo opzioni che eliminano le parti che non desidera elaborare.

Sulla moderna Debian ottieni il tuo file con:

ls --format=single-column 

Inoltre, non devi prestare attenzione alla directory in cui lo stai eseguendo se usi la directory completa:

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

Questo ultimo comando sto usando quanto sopra e ottengo il seguente output:

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.