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
.
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
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
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
.
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' *
find /path/to/directory '!' -name '*.pdf' '!' -name '*.txt'
C'est équivalent à la commande avec l'opérateur OR, à cause des lois de De Morgan .
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é.
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.
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.