Itération sur chaque ligne de sortie ls -l


120

Je veux parcourir chaque ligne dans la sortie de: ls -l /some/dir/*

En ce moment, j'essaye: for x in $(ls -l $1); do echo $x; done

Cependant, cela itère sur chaque élément de la ligne séparément, donc j'obtiens:

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

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

Mais je veux parcourir chaque ligne dans son ensemble, cependant. Comment je fais ça?


1
Citez toujours les variables (et la sortie de commande) sauf si vous avez une raison spécifique de ne pas le faire.
glenn jackman

Réponses:


247

Définissez IFS sur une nouvelle ligne, comme ceci:

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

Mettez un sous-shell autour de lui si vous ne voulez pas définir IFS de manière permanente:

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

Ou utilisez while | lire à la place:

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

Une autre option, qui exécute while / read au même niveau du shell:

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

12
Méfiez-vous lors du piping vers while, le while s'exécutera dans un sous-shell, ce qui signifie qu'il ne pourra pas changer les variables dans le processus principal
Reorx

1
Que fait le dollar ici? J'ai besoin de l'utiliser dans un script que j'écris qui accepte les arguments. Le $ 1 jette les choses. Que puis-je mettre là au lieu de 1 $ pour obtenir le même effet? Je voudrais utiliser la deuxième solution.
noob-in-need

@ noob-in-need Remplacez-le par le répertoire que vous voulez lister
vpzomtrrfrt

1
Vous voudrez peut-être faire, read -rsinon bash supprimera les contre-obliques non échappées des données.
Brian Gordon

6

Cela dépend de ce que vous voulez faire avec chaque ligne. awk est un utilitaire utile pour ce type de traitement. Exemple:

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

.. sur mon système imprime le nom et la taille de chaque élément du répertoire.


3

Comme déjà mentionné, awk est le bon outil pour cela. Si vous ne voulez pas utiliser awk, au lieu d'analyser la sortie de "ls -l" ligne par ligne, vous pouvez parcourir tous les fichiers et faire un "ls -l" pour chaque fichier individuel comme ceci:

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

3

Vous pouvez également essayer la findcommande. Si vous ne voulez que des fichiers dans le répertoire courant:

find . -d 1 -prune -ls

Exécuter une commande sur chacun d'eux?

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

Compter les lignes, mais uniquement dans les fichiers?

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


trouver est cassé. Je reçois souvent des messages d'erreur bizarro. il veut m'aider lorsque la ligne de commande est parfaitement valide, et il semble qu'une fois qu'il commence à le faire, il ne s'arrêtera pas avant le prochain redémarrage PEUT-ÊTRE. il semble parfois de nature aléatoire concernant les erreurs. ne sais pas comment je peux signaler le bogue.
Jim Michaels

1

L'utilitaire read (1) avec la redirection de sortie de la commande ls (1) fera ce que vous voulez.


-1

Alors, pourquoi personne n'a suggéré d'utiliser simplement des options qui éliminent les parties qu'il ne veut pas traiter.

Sur Debian moderne, vous obtenez simplement votre fichier avec:

ls --format=single-column 

De plus, vous n'avez pas à faire attention au répertoire dans lequel vous l'exécutez si vous utilisez le répertoire complet:

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

Cette dernière commande que j'utilise ci-dessus et j'obtiens la sortie suivante:

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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.