encontra nomes de arquivos que NÃO terminam em extensões específicas no Unix?

207

Existe uma maneira simples de encontrar recursivamente todos os arquivos em uma hierarquia de diretórios que não terminam em uma lista de extensões? Por exemplo, todos os arquivos que não são * .dll ou * .exe

A localização do UNIX / GNU, por mais poderosa que pareça, não parece ter um excludemodo (ou estou sentindo falta dele), e sempre achei difícil usar expressões regulares para encontrar coisas que não correspondem a uma expressão específica .

Estou em um ambiente Windows (usando a porta GnuWin32 da maioria das ferramentas GNU), então estou igualmente aberto para soluções somente para Windows.

Cristian Diaconescu
fonte

Respostas:

343

Ou sem (e a necessidade de escapar:

find . -not -name "*.exe" -not -name "*.dll"

e também excluir a listagem de diretórios

find . -not -name "*.exe" -not -name "*.dll" -not -type d

ou em lógica positiva ;-)

find . -not -name "*.exe" -not -name "*.dll" -type f
Hardy
fonte
6
-notpode ser substituído por '!'(é recomendável citar). Por outro lado, -nameé sensível a -inamemaiúsculas e minúsculas.
Ivan Chau
45
find . ! \( -name "*.exe" -o -name "*.dll" \)
Chen Levy
fonte
2
No Solaris -noté uma má opção, desta vez com !obras nice :)
DmitrySandalov
8
$ find . -name \*.exe -o -name \*.dll -o -print

As primeiras opções com dois nomes não têm opção de impressão, portanto, foram ignoradas. Todo o resto é impresso.

Jeff Ferland
fonte
4

Você pode fazer algo usando o comando grep:

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

A -vbandeira no grepsignifica especificamente "encontrar coisas que não correspondem a essa expressão".

VoteyDisciple
fonte
6
grep -v '\. (dll | exe) $' impediria a correspondência novamente em um arquivo ou diretório chamado "dexe", por exemplo
drAlberT 27/08/09
Isso funciona apenas com regexp estendido. Eu tive que adicionar -E (ou usar o egrep) para fazer isso funcionar.
Joctee
2

mais um :-)

$ ls -ltr
10 total
-rw-r - r-- 1 script linuxdumb 47 dez 23 14:46 test1
-rw-r - r-- 1 scripter linuxdumb 0 de jan 4 23:40 test4
-rw-r - r-- 1 scripter linuxdumb 0 de jan 4 23:40 test3
-rw-r - r-- 1 scripter linuxdumb 0 de jan 4 23:40 test2
-rw-r - r-- 1 scripter linuxdumb 0 de jan 4 23:41 file5
-rw-r - r-- 1 scripter linuxdumb 0 de jan 4 23:41 file4
-rw-r - r-- 1 scripter linuxdumb 0 de jan 4 23:41 file3
-rw-r - r-- 1 scripter linuxdumb 0 de jan 4 23:41 file2
-rw-r - r-- 1 scripter linuxdumb 0 de jan 4 23:41 file1
$ find. -tipo f! -name "* 1"! -name "* 2" -print
./test3
./test4
./file3
./file4
./file5
$

Referência do comando find do Unix

lógica
fonte
1
find  /data1/batch/source/export   -type f -not  -name "*.dll" -not -name "*.exe"
gwecho huang
fonte
1

Linux / OS X:

A partir do diretório atual, localize recursivamente todos os arquivos que terminam em .dll ou .exe

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

A partir do diretório atual, encontre recursivamente todos os arquivos que NÃO terminam em .dll ou .exe

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

Notas:

(1) A opção P no grep indica que estamos usando o estilo Perl para escrever nossas expressões regulares a serem usadas em conjunto com o comando grep . Com o objetivo de executar o comando grep em conjunto com expressões regulares, acho que o estilo Perl é o estilo mais poderoso existente.

(2) A opção v no grep instrui o shell a excluir qualquer arquivo que satisfaça a expressão regular

(3) O caractere $ no final de dizer ".dll $" é um caractere de controle delimitador que informa ao shell que a string do nome do arquivo termina com ".dll"

Vietnhi Phuvan
fonte
0

Outras soluções nesta página não são desejáveis ​​se você tiver uma longa lista de extensões - a manutenção de uma longa sequência -not -name 'this' -not -name 'that' -not -name 'other'seria tediosa e propensa a erros - ou se a pesquisa for programática e a lista de extensões for criada em tempo de execução.

Para essas situações, uma solução que separa mais claramente dados (a lista de extensões) e código (os parâmetros para find) pode ser desejável. Dada uma estrutura de diretório e arquivo que se parece com isso:

.
└── 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

Você pode fazer algo assim:

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

O que resulta em:

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

Você pode alterar a lista de extensões sem alterar o bloco de código.

NOTA não funciona com OSX nativo find- use o gnu find.

Chris Johnson
fonte