Comment lister des fichiers sans répertoires et filtrer par nom (options ls)

42

J'ai un répertoire appelé uploads. Il contient un tas de fichiers, ainsi que quelques sous-répertoires qui contiennent à leur tour des fichiers.

Y a-t-il un moyen que je puisse (en une étape) faire ce qui suit:

  1. Répertoriez SEULEMENT les fichiers du répertoire racine uploads - je ne souhaite pas voir les noms des sous-dossiers ni leur contenu;

    et

  2. Ne listez pas les fichiers qui commencent par t_

Je connais le -ddrapeau, mais cela ne me donne pas tout à fait ce que je veux.

EmmyS
la source

Réponses:

53

Cela ressemble à un travail pour find.

  • Utiliser -maxdepthpour ne renvoyer que le répertoire en cours, pas de recherche récursive dans les sous-dossiers
  • Utiliser -type fpour ne renvoyer que des fichiers et non des répertoires, des nœuds de périphériques ou autre chose
  • Utilisez une combinaison si -notet -namepour éviter les fichiers avec des noms que vous ne voulez pas

Cela pourrait venir comme ceci:

find /path/to/uploads -maxdepth 1 -type f -not -name 't_*'
Caleb
la source
Merci! Je suis assez nouveau pour CLI et je n'avais jamais utilisé find avant. Je vais certainement aller plus loin.
EmmyS
2
@EmmyS: Vous pourriez trouver une petite astuce utile ici. @ Gilles a mentionné utiliser -exec ls -lG -- {} +dans sa réponse pour obtenir la sortie en utilisant des options supplémentaires à ls. Vous pouvez également ajouter simplement une valeur -lsà cette recherche pour obtenir une approximation rapide et approximative de la vue détaillée de ls.
Caleb
18

GNU ls (c’est-à-dire la commande ls sur les systèmes Linux non intégrés et Cygwin, également disponible sur d’autres unités de travail) dispose d’une option permettant de masquer certains fichiers, en fonction de leur nom. Il n'y a aucun moyen d'ignorer les répertoires.

ls --hide='t_*' uploads

Une autre approche consiste à faire correspondre votre shell. Bash, ksh et zsh ont un motif de négation !(t_*)correspondant à tous les fichiers sauf ceux qui correspondent t*; dans bash, cette fonctionnalité doit être activée avec shopt -s extglob, et en zsh, elle doit être activée avec setopt ksh_glob. Zsh a également la syntaxe équivalente ^t_*qui doit être activée avec setopt extended_glob. Cela n'ignore toujours pas les répertoires. Zsh possède une fonctionnalité supplémentaire qui permet de faire correspondre les fichiers non seulement par leur nom, mais également par les métadonnées et plus encore: les qualificatifs glob . Ajoutez (.)à la fin d'une correspondance pour limiter les fichiers normaux. La négation ^fait partie de la syntaxe de correspondance de nom, ainsi ^t_*(.)signifie «tous les fichiers normaux ne correspondent pas t_*» et non «tous les fichiers qui ne correspondent pas t_*».

setopt extended_glob  # put this in your ~/.zshrc
ls uploads/^t_*(.)

Si vous vous trouvez sans outils avancés, vous pouvez le faire sur n'importe quel unix avec find. Ce n'est pas le genre de chose que vous tapez habituellement sur la ligne de commande, mais c'est puissant et précis. Caleb a déjà montré comment faire cela avec GNU Find . L' -maxdepthoption n'est pas portable. vous pouvez utiliser à la -pruneplace, pour arrêter findde manière portable de récursir.

find uploads/* -type d -prune -o \! -type f -name 't_*' -print

Remplacer -printpar -exec ls -lG -- {} +pour exécuter lsavec vos options préférées sur les fichiers.

Toutes les commandes ci-dessus masquent les fichiers à points (c'est-à-dire les fichiers dont le nom commence par a .). Si vous souhaitez les afficher, passez -Aà lsou ajoutez le Dqualificatif glob dans zsh ( ls uploads/^t_*(.D)). Avec find, vous pouvez utiliser une approche différente pour le faire récidiver à un niveau seulement ( findne traite pas spécialement les fichiers à points). Cela ne fonctionne pleinement que si vous exécutez finddans le répertoire en cours.

cd uploads && find . -name . -o -type d -prune -o \! -type f -name 't_*' -print
Gilles, arrête de faire le mal
la source
3
Avez-vous un dayjob? ;-) Je suis toujours étonné par la longueur et le niveau de détail de vos réponses, même pour les questions les plus simples ici à Unix SE! .. Continuez quand même! :)
alex
Merci! Grand détail. Je ne sais pas si j'ai des "outils avancés" ou pas maintenant; Je suis sur un Mac au travail (bien que Linux à la maison, donc je suis sûr que cela sera utile à un moment donné.)
EmmyS
@EmmyS: Pour votre machine Linux, mon utilisation de -maxdepthdevrait fonctionner, mais le problème de "portabilité" mentionné par Gilles est que le BSD find(également disponible sous OSX) est un animal un peu différent, vous pourriez donc avoir besoin de sa réponse. @ Gilles: +1 pour le tour de zsh!
Caleb le
1
@Gilles: Certains commentaires pas si juteux à propos de sa pruneviennent à l'esprit, mais je vais laisser passer ça en disant simplement que lorsque je bricole sur mes propres systèmes le nombre de fois que la pensée " cette commande fonctionnerait-elle si j'étais sur AIX, Solaris ou MINIX3 "est à peu près ... en attente ... Je ne parviens pas à obtenir un relevé de compteur ... l'affichage est figé 0.00.
Caleb
2
Gnu lsn'a pas une --use-telepathyoption? C'est le moyen le plus rapide d'afficher uniquement les fichiers de votre choix. Cela pourrait ne pas être portable cependant.
dubiousjim
8
ls -l /folder | grep ^- | awk '{print $9}'
Krayher
la source
Qu'y a-t-il $9dans cette déclaration?
EmmyS
3
@EmmyS Cela signifie que le 9ème champ / colonne de la sortie. Cette réponse tente d' analyser la lssortie .
jw013
print $ NF` serait mieux, IMO. $ NF signifie nombre de champs, ce qui serait 9 et est une utilisation courante dans AWK comme une bonne opportunité d'enseigner aux autres sur $ NF.
Elijah Lynn
1
ls -l | grep -v ^d | grep name$
RICARDO MARMOLEJO GARCIA
la source
En quoi cette solution (qui nécessite plusieurs commandes et tuyaux) est-elle préférable find?
HalosGhost
Il est concis, facile à lire et reste conforme à la convention de commande ls. Je trouve plus facile à retenir que les arguments de la commande find. À chacun ses propres et bravo pour les options!
tkjef
0

Laisse-moi essayer lset utiliser des pipes:

ls  -l --hide='t_*'  uploads/ | grep -v ^d | tr -s ' ' | cut -d ' ' -f 9

disons que la dernière colonne est la 9ème.

Y0NG
la source
1
Et s'il y a des fichiers avec des espaces?
Jordanie
0

Si le problème de la portabilité -maxdepth de find est un problème, vous pouvez utiliser:

ls -l uploads/ | awk '/^-/ && $9 !~/^t_/ {print $9}'

Je ne suis pas un expert, mais je pense que cela devrait fonctionner. Je suppose que cela a l'air un peu cryptique, mais si vous parlez mal, ce n'est vraiment pas le cas. $ NF pourrait être utilisé au lieu de 9 $. Vous pouvez aussi faire:

ls -l uploads/ | awk '/^-/' | awk '!/^t_/ {print $9}'

qui fait la même chose (mais peut-être moins efficacement que l'ancien ???).

En fait, après avoir pensé aux autres posts, on dirait que

ls -l --hide=t_* uploads/ | awk '/^-/ {print $9}'

est un moyen encore plus court et plus clair.

Quelqu'un s'il vous plaît corrigez-moi si je me trompe. :-)

Kkaszub
la source
L'analyse lsn'est généralement pas une bonne idée . Vos astuces awk échoueront avec les noms de fichiers contenant des espaces, par exemple.
Mat
@mat - Merci pour la correction. Après avoir lu l'article que vous (et jw013) avez souligné, je constate qu'il est impossible de faire confiance à ls pour la sortie de noms de fichiers corrects. Même si je devais réécrire le code awk pour imprimer tout de 9 $ à la fin de la ligne (pour contenir des espaces vides), cette ls sortie peut encore être erronée. Ceci est décevant et devrait être corrigé à l’OMI. Merci encore.
kkaszub
0

J'ai trouvé ces petites manières:

ls -p uploads | grep -Ev '/'

ou

ls -pIt_* uploads | grep -v /
Radu Rădeanu
la source
-1

Essayez cet alias et utilisez-le:

alias l='ls -hLlF'
Granulaire
la source
ls -hLlFaffiche les sous-répertoires et les fichiers commençant par t_. Alors, comment cela répond-il à la question?
Raphael Ahrens
J'ai peut-être mal compris la question. ls -hLlF n'affichera pas les répertoires cibles des répertoires liés.
Granulaire
Semble si. Mais n'avez-vous pas lu les autres réponses à la question?
Raphael Ahrens
-1

Peasy facile:

ls -l --hide 't_*' <absolute path to desired directory> | grep -v ^d

Excavateur
la source
(1) Cette réponse est si facile, elle a déjà été donnée. (2) Pourquoi pensez-vous que vous devez spécifier le chemin d'accès complet au répertoire?
Scott
@Scott - C’est un moyen très simple et rapide de trouver la solution. Le chemin complet a été spécifié pour rendre la réponse universelle ...
Digger