web-dev-qa-db-fra.com

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

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 lister tous les fichiers sauf les fichiers . Txt, alors soit

find -not -iname "*.txt"

ou

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

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

31
Andrew

En supposant que l'on a GNU 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
31
Dejian

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 ne devez pas analyser la sortie de ls )

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

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

12
jw013

Dans zsh avec 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 fonction FIGNORE (mis):

FIGNORE='@(.|..|*.txt|*.pdf)'
printf '%s\n' *
6
Thor
find /path/to/directory '!' -name '*.pdf' '!' -name '*.txt'

C'est équivalent à la commande avec l'opérateur OR, à cause des lois de De Morgan .

4
Francesco Turco

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

GNU (et certains BSD) find supporte le -print0 pré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 en aura pas une 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 voulez exécuter xargs -r0 en conjonction avec la recherche de -print0 Par exemple:

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

Ceci 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 tar comme 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

rsync accepte également les fichiers délimités par des valeurs nulles avec le -0, comme plusieurs autres. Mais xargs est la colle que vous utiliserez habituellement pour ce type d'utilisation. Soit cela, soit find-exec fonctionnalité.

3
tylerl

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
abu_bua

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.

0
Sylvain Leroux