UNIX find pour trouver des noms de fichiers ne se terminant pas par des extensions spécifiques?
Existe-t-il un moyen simple de trouver récursivement tous les fichiers d'une hiérarchie de répertoires, qui ne se terminent pas par une liste d'extensions? Par exemple, tous les fichiers qui ne sont pas *.dll ou *.exe
Unix / GNU find, aussi puissant soit-il, ne semble pas avoir de mode exclude
(ou il me manque), et j'ai toujours eu du mal à utiliser des expressions régulières pour trouver des choses qui ne correspondent pas à une expression particulière.
Je suis dans un environnement Windows (en utilisant le port GnuWin32 de la plupart des GNU outils), donc je suis également ouvert pour les solutions Windows uniquement.
8 réponses
Ou sans (
et la nécessité d'y échapper:
find . -not -name "*.exe" -not -name "*.dll"
Et d'exclure également la liste des répertoires
find . -not -name "*.exe" -not -name "*.dll" -not -type d
Ou en logique positive ;-)
find . -not -name "*.exe" -not -name "*.dll" -type f
$ find . -name \*.exe -o -name \*.dll -o -print
Les deux premières options de nom n'ont pas d'option d'impression, elles ont donc sauté. Tout le reste est imprimé.
Vous pouvez faire quelque chose en utilisant la commande grep:
find . | grep -v '(dll|exe)$'
Le drapeau -v
sur grep
signifie spécifiquement " trouver des choses qui ne correspondent pas à cette expression."
Un de plus :-)
$ ls -ltr total 10 -rw-r--r-- 1 scripter linuxdumb 47 Dec 23 14:46 test1 -rw-r--r-- 1 scripter linuxdumb 0 Jan 4 23:40 test4 -rw-r--r-- 1 scripter linuxdumb 0 Jan 4 23:40 test3 -rw-r--r-- 1 scripter linuxdumb 0 Jan 4 23:40 test2 -rw-r--r-- 1 scripter linuxdumb 0 Jan 4 23:41 file5 -rw-r--r-- 1 scripter linuxdumb 0 Jan 4 23:41 file4 -rw-r--r-- 1 scripter linuxdumb 0 Jan 4 23:41 file3 -rw-r--r-- 1 scripter linuxdumb 0 Jan 4 23:41 file2 -rw-r--r-- 1 scripter linuxdumb 0 Jan 4 23:41 file1 $ find . -type f ! -name "*1" ! -name "*2" -print ./test3 ./test4 ./file3 ./file4 ./file5 $
Linux / OS X:
À partir du répertoire courant, recherchez récursivement tous les fichiers se terminant par .dll ou .exe
find . -type f | grep -P "\.dll$|\.exe$"
À partir du répertoire courant, recherchez récursivement tous les fichiers qui ne se terminent pas .dll ou .exe
find . -type f | grep -vP "\.dll$|\.exe$"
Notes:
(1) L'option P sur grep indique que nous utilisons le style Perl pour écrire nos expressions régulières à utiliser conjointement avec la commande grep. Dans le but d'excécuter la commande grep dans en conjonction avec les expressions régulières, je trouve que le style Perl est le style le plus puissant autour.
(2) l'option v sur grep indique au shell d'exclure tout fichier qui satisfait l'expression régulière
(3) le caractère $ à la fin de say ".dell$" est un caractère de contrôle de délimiteur qui indique au shell que la chaîne de nom de fichier se termine par ".dll "
D'autres solutions sur cette page ne sont pas souhaitables si vous avez une longue liste d'extensions-maintenir une longue séquence de -not -name 'this' -not -name 'that' -not -name 'other'
serait fastidieux et sujet aux erreurs-ou si la recherche est programmatique et la liste des extensions est construite au moment de l'exécution.
Pour ces situations, une solution qui sépare plus clairement les données (la liste des extensions) et le code (les paramètres à find
) peut être souhaitable. Étant donné une structure de répertoire et de fichier qui ressemble à ceci:
.
└── a
├── 1.txt
├── 15.xml
├── 8.dll
├── b
│ ├── 16.xml
│ ├── 2.txt
│ ├── 9.dll
│ └── c
│ ├── 10.dll
│ ├── 17.xml
│ └── 3.txt
├── d
│ ├── 11.dll
│ ├── 18.xml
│ ├── 4.txt
│ └── e
│ ├── 12.dll
│ ├── 19.xml
│ └── 5.txt
└── f
├── 13.dll
├── 20.xml
├── 6.txt
└── g
├── 14.dll
├── 21.xml
└── 7.txt
Vous pouvez faire quelque chose comme ceci:
## data section, list undesired extensions here
declare -a _BADEXT=(xml dll)
## code section, this never changes
BADEXT="$( IFS="|" ; echo "${_BADEXT[*]}" | sed 's/|/\\|/g' )"
find . -type f ! -regex ".*\.\($BADEXT\)"
, Qui se traduit par:
./a/1.txt
./a/b/2.txt
./a/b/c/3.txt
./a/d/4.txt
./a/d/e/5.txt
./a/f/6.txt
./a/f/g/7.txt
Vous pouvez modifier la liste des extensions sans modifier le bloc de code.
NOTE ne fonctionne pas avec OSX natif find
- utilisez gnu find à la place.
find /data1/batch/source/export -type f -not -name "*.dll" -not -name "*.exe"