Comment lister tous les fichiers d'un répertoire sauf ceux avec les extensions spécifiées?


28

Supposons que j'ai un dossier contenant .txt , .pdf et d'autres fichiers. Je voudrais lister les "autres" fichiers (c'est-à-dire les fichiers n'ayant pas les extensions .txt ou .pdf ). Avez-vous des conseils sur la façon de procéder?

Je sais comment lister les fichiers n'ayant pas d'extension donnée. Par exemple, si je veux répertorier tous les fichiers à l'exception des fichiers .txt , alors soit

find -not -iname "*.txt"

ou

ls | grep -v '\.txt$' | column

semblent fonctionner. Mais, comment puis-je lister tout sauf les fichiers .txt ou les fichiers .pdf ? Il semble que je doive utiliser une sorte de "ou" logique dans findou grep.


2
Gardez à l'esprit que le comportement de lsvs findvs globbing peut différer pour les fichiers dot cachés.
jw013

1
Une autre chose à garder à l'esprit: findtraversera les sous-répertoires, comme un récursif ls. Utilisez -maxdepth 1avec findpour qu'il se comporte plus comme ls.
jw013

Donc pas récursif, listez simplement les fichiers dans le répertoire courant?
marguerite

Réponses:


28

En supposant que l'on dispose d'une version appropriée de ls, c'est probablement la manière la plus simple:

ls -I "*.txt" -I "*.pdf"

Si vous souhaitez parcourir tous les sous-répertoires:

ls -I "*.txt" -I "*.pdf" -R

8
Les lsoptions GNU ne sont pas portables.
bahamat

4
lsn'appartient pas vraiment aux scripts portables de toute façon, donc je suppose que l'OP pose des questions sur l'utilisation interactive uniquement.
jw013

1
Pourquoi ls n'est pas portable? Que dois-je utiliser alors?
Freedo

28

Trouver des supports -o

find . ! '(' -name '*.txt' -o -name '*.pdf' ')'

Vous avez besoin des parenthèses pour faire la priorité. Find fait beaucoup de choses; Je suggère de lire sa page de manuel.

Vous pouvez également faire un ou dans grep(mais vraiment, vous nels devez pas analyser la sortie de )

ls | grep -Ev '\.(txt|pdf)$' | column

1
Merci! Pourquoi ne devrais-je pas analyser la sortie de ls?
Andrew

6
@Andrew d'abord, car il est fragile (pensez à un nom de fichier avec une nouvelle ligne - oui, c'est un nom de fichier valide -, trouvez -print0 / -exec / -delete / etc. Évitez ce problème); deuxièmement, car il existe généralement un moyen plus simple.
derobert

En plus de la findpage de manuel, je recommande sans réserve les articles Unix Power Tools find, tels que docstore.mik.ua/orelly/unix3/upt/ch09_06.htm et docstore.mik.ua/orelly/unix3/upt/ch09_12.htm
Wildcard

Juste pour aider à décoder la déclaration pour les humains:find . NOT ( *.txt OR *.pdf )
wisbucky

12

Avec bashun globbing étendu (activer avec shopt -s extglob), le glob !(*.txt|*.pdf)devrait fonctionner. Vous pouvez transmettre ce glob directement à n'importe quelle commande qui accepte des arguments de fichier, y compris mais sans s'y limiter ls.


1
+1 mais si vous avez des sous-répertoires, leur contenu sera également répertorié; utiliser -dpour éviter cela:ls -d !(*.txt|*.pdf)
legends2k

Merci, je cherchais exactement la syntaxe pour accepter plusieurs fichiers, cela irait bien ici stackoverflow.com/questions/216995/…
Freedo

6

En zshavec extendedglob:

print -rl -- *~*.(txt|pdf)

ou

print -rl -- ^*.(txt|pdf)

Ou avec kshglob(oui, c'est ksh globbing pas "bash extended globbing"):

print -rl -- !(*.txt|*.pdf)

N'oubliez pas que ceux-ci excluent également les fichiers dot.

ksh93 a la FIGNORE(mauvaise) fonctionnalité:

FIGNORE='@(.|..|*.txt|*.pdf)'
printf '%s\n' *


3

Comme suggéré par derobert, votre meilleur pari est d'utiliser find. Cependant, vous pouvez en fait utiliser le résultat dans un pipeline avec d'autres commandes.

GNU (et certains BSD) findprennent en charge le -print0prédicat qui lui indique d'imprimer le nom de fichier terminé par un caractère NUL , lequel caractère n'est pas autorisé dans un nom de fichier et garantit qu'il n'y aura pas de collision. D'autres commandes peuvent être chargées d'utiliser le NUL comme délimiteur d'entrée.

Le plus important est GNU xargs, qui exécute la commande que vous spécifiez et lui transmet la liste des fichiers comme arguments de ligne de commande. Vous souhaitez exécuter xargs -r0conjointement avec find -print0Par exemple:

find . -type f ! \( -name \*.pdf -o -name \*.txt \) -print0 | xargs -r0 ls -ld

Cela imprime en toute sécurité une longue liste de répertoires de tous les fichiers pdf et txt , y compris ceux avec des espaces ou des caractères non imprimables dans le nom.

Vous pouvez également l'utiliser avec GNU tarcomme suit:

tar -zcf myarchive.tar.gz --null --files-from <(
  find . -type f ! -name \*.tar.gz -print0)

Cela crée un fichier tar.gz de tous les fichiers dont les noms ne se terminent pas par .tar.gz

rsyncaccepte également les fichiers délimités par des valeurs nulles avec le -0paramètre, tout comme plusieurs autres. Mais xargsc'est la colle que vous utiliserez habituellement pour ce type de but. Soit cela, soit findla -execfonctionnalité de.


L' tarexemple de commande est bon. Pour la plupart des objectifs, cependant, -execest un meilleur ajustement.
Wildcard

1

Si vous n'avez pas de sous-répertoire

ls !(*.pdf|*.txt)

devrait également fonctionner!

Mais

ls -I "*.pdf" -I "*.txt"

est la voie commune.


0

En complément, si vous utilisez un shell compatible bash, vous pouvez utiliser la variable GLOBIGNORE pour exclure les résumés de la correspondance de modèle. De l'homme:

   GLOBIGNORE
          A colon-separated list of patterns defining the set of filenames
          to be ignored by pathname expansion.  If a filename matched by a
          pathname  expansion  pattern also matches one of the patterns in
          GLOBIGNORE, it is removed from the list of matches.

Dans votre cas particulier:

sh$ (GLOBIGNORE='*.pdf:*.txt'; ls -d *)

Veuillez noter que j'exécute cette commande en tant que sous-shell (en utilisant des parenthèses) afin de ne pas modifier la variable d'environnement GLOBIGNORE de mon shell interactif.

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.