Comment sélectionner un champ / une colonne dans la sortie de `ls -l`?

22

Mon objectif est d'une simplicité trompeuse (du moins pour moi). Je souhaite prendre la sortie de ls -lou ls -lhet sélectionner un seul champ.

Je cherche à ce que cela soit aussi à l'épreuve des balles que possible, c'est-à-dire que je suppose que les noms de fichiers peuvent avoir un nombre variable d'espaces, tout sur le terrain n'a pas la même longueur, etc.

Points bonus pour avoir un script qui prendra le nom du champ (ou même juste un numéro de champ), puis retournera le contenu du champ.

Je veux tourner

entrez la description de l'image ici

dans:

entrez la description de l'image ici

soandos
la source

Réponses:

41

Essayez ls -l | awk '{print $7}'.

awk sélectionne les colonnes, il est donc parfait pour cette tâche.

Corey Whitaker
la source
3
Comme expliqué par @ormaaj: Ne comptez pas sur des éléments d'information disponibles dans des endroits spécifiques avec ls. La findcommande est extrêmement utile.
Paddy Landau
@PaddyLandau Comment utiliser la commande find pour imprimer une taille de fichier en mégaoctets comme je peux avec ls -l --block-size=M?
SurpriseDog
@Benjamin - La lscommande n'est pas standard POSIX, donc un script qui en dépend lspourrait se casser sur différents systèmes ou même au fil du temps. Voir la réponse de @ormaaj sur cette page pour plus de détails. Une façon de faire ce que vous demandez est avec une boucle Bash. Voici un exemple. for FILENAME in *; do FILESIZE=$(( $( stat --format=%s "${FILENAME}" ) / 1024 )); echo "${FILENAME}" ${FILESIZE}; done. Bien sûr, au lieu de echo, vous utiliseriez votre traitement.
Paddy Landau
@PaddyLandau Je viens de finir de diriger la sortie de la commande find ... | xargs -d '\n' du -mqui fonctionne aussi bien.
SurpriseDog
@Benjamin Vous voudrez peut-être examiner l' -execoption de find.
Paddy Landau
17

Ne jamais analyser ls . Utilisez GNU find. Ou si la portabilité est pas important, stat(1).

find . -maxdepth 1 -printf '%Td\n'

Pour lire des données autres que des listes de noms de fichiers ligne par ligne et les diviser en champs, voir: BashFAQ / 001

Il n'existe aucune méthode pour lire de manière fiable une liste de noms de fichiers délimités par des sauts de ligne qui ont du sens dans la plupart des circonstances.

ormaaj
la source
1

Vous pouvez récupérer la colonne spécifique dans le shell comme:

ls -al | while read perm bsize user group size month day time file; do echo $day; done

ou awkcomme indiqué dans la réponse @Corey , cut -c44-45fonctionnerait également après ajustement (car lsa des colonnes fixes), ou quoi que ce soit d'autre, mais le principal problème est qu'il ne sera pas fiable et à l'épreuve des balles (par exemple sur Unix, il peut l'être $6, non $7, et il change en fonction des arguments), ce qui le rend non convivial pour la machine, il n'est donc pas recommandé d'analyser la lscommande du tout.

Le mieux est d'utiliser différentes commandes disponibles telles que findou stat, qui peuvent fournir des options pertinentes pour formater la sortie selon vos besoins. Par exemple:

$ stat -c "%x %n" *
2016-04-10 04:53:07.000000000 +0100 001.txt
2016-04-10 05:08:42.000000000 +0100 7c1c.txt

Pour renvoyer une colonne de seulement jours de modifications, essayez cet exemple:

stat -c "%x" * | while read ymd; do date --date="$ymd" "+%d"; done

Il convient de noter que GNU statpourrait avoir des options différentes de BSD stat, il ne sera donc toujours pas à l'épreuve des balles sur différents systèmes d'exploitation.

kenorb
la source
1
+1 pour mentionner que ls ne doit pas être analysé ainsi que pour l'utilisation de stat. datecependant est mal configuré. Vous devez ajouter --date=$ymd, car dateen soi imprimera le jour en cours, mais le but ici est de convertir le format de date du fichier
Sergiy Kolodyazhnyy
La ls -la | cut -c32-33commande en toute honnêteté n'est tout simplement pas fiable, non seulement en raison des pièges possibles avec les noms de fichiers, mais simplement parce qu'elle dépend de la longueur des noms d'utilisateur et de la taille des fichiers. La stat -c "%x" *.*commande semble correcte, mais en l'utilisant, *.*vous la restreignez uniquement aux noms de fichiers contenant un point. Je suppose que l'intention était d'attraper également des fichiers cachés; dans ce cas , vous devez activer les jokers pour dotfiles au préalable et utiliser au *lieu de *.*: shopt -s dotglob; stat -c "%x" * | [...].
kos
Ah et ce que Serg a dit aussi, vous devez ajouter --date="$ymd"à la datecommande, sinon il imprimera le jour actuel du mois.
kos
Merci pour les commentaires. J'ai résolu les problèmes et fourni un meilleur exemple initial.
kenorb