trouver des noms de fichiers ne se terminant pas par des extensions spécifiques sous Unix?

207

Existe-t-il un moyen simple de rechercher 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

La recherche UNIX / GNU, aussi puissante soit-elle, ne semble pas avoir de excludemode (ou je le 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 outils GNU), donc je suis également ouvert aux solutions Windows uniquement.

Cristian Diaconescu
la source

Réponses:

343

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
Robuste
la source
6
-notpeut être remplacé par '!'(Devis recommandé). D'un autre côté, -nameest sensible à la casse alors qu'il -inameest insensible à la casse.
Ivan Chau
45
find . ! \( -name "*.exe" -o -name "*.dll" \)
Chen Levy
la source
2
Sous Solaris -notest une mauvaise option, celle-ci !fonctionne bien :)
DmitrySandalov
8
$ find . -name \*.exe -o -name \*.dll -o -print

Les deux premières options de nom n'ont pas d'option -print, elles ont donc été ignorées. Tout le reste est imprimé.

Jeff Ferland
la source
4

Vous pouvez faire quelque chose en utilisant la commande grep:

find . | grep -v '(dll|exe)$'

Le -vdrapeau sur grepsignifie spécifiquement "trouver des choses qui ne correspondent pas à cette expression".

VoteyDisciple
la source
6
grep -v '\. (dll | exe) $' empêcherait la correspondance avec un fichier ou un répertoire nommé "dexe" par exemple
drAlberT
Cela ne fonctionne qu'avec une expression rationnelle étendue. J'ai dû ajouter -E (ou utiliser egrep) pour que cela fonctionne.
joctee
2

un de plus :-)

$ ls -ltr
10 au total
-rw-r - r-- 1 scripteur linuxdumb 47 déc 23 23:46 test1
-rw-r - r-- 1 scripteur linuxdumb 0 4 janvier 23:40 test4
-rw-r - r-- 1 scripteur linuxdumb 0 4 janvier 23:40 test3
-rw-r - r-- 1 scripteur linuxdumb 0 4 janvier 23:40 test2
-rw-r - r-- 1 scripteur linuxdumb 0 4 janvier 23:41 file5
-rw-r - r-- 1 scripteur linuxdumb 0 4 janvier 23:41 file4
-rw-r - r-- 1 scripteur linuxdumb 0 4 janvier 23:41 file3
-rw-r - r-- 1 scripteur linuxdumb 0 4 janvier 23:41 file2
-rw-r - r-- 1 scripteur linuxdumb 0 4 janvier 23:41 file1
$ find. -type f! -nom "* 1"! -name "* 2" -print
./test3
./test4
./fichier3
./fichier4
./fichier5
$

Référence de la commande de recherche Unix

logique
la source
1
find  /data1/batch/source/export   -type f -not  -name "*.dll" -not -name "*.exe"
gwecho huang
la source
1

Linux / OS X:

À partir du répertoire actuel, recherchez récursivement tous les fichiers se terminant par .dll ou .exe

find . -type f | grep -P "\.dll$|\.exe$"

À partir du répertoire actuel, recherchez récursivement tous les fichiers qui ne se terminent pas par .dll ou .exe

find . -type f | grep -vP "\.dll$|\.exe$"

Remarques:

(1) L'option P dans 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'exécuter la commande grep en conjonction avec des expressions régulières, je trouve que le style Perl est le style le plus puissant qui soit.

(2) L'option v dans grep demande au shell d'exclure tout fichier qui satisfait l'expression régulière

(3) Le caractère $ à la fin de dire ".dll $" 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"

Vietnhi Phuvan
la source
0

D'autres solutions sur cette page ne sont pas souhaitables si vous avez une longue liste d'extensions - maintenir une longue séquence -not -name 'this' -not -name 'that' -not -name 'other'serait fastidieuse et sujette 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épertoires et de fichiers 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 ça:

## 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\)"

Ce 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.

REMARQUE ne fonctionne pas avec OSX natif find- utilisez plutôt gnu find.

Chris Johnson
la source