Como encontrar arquivos com extensões específicas, excluindo apenas alguns nomes no diretório atual?

3

Eu quero encontrar alguns arquivos, em um ambiente não-GNU

  • apenas no diretório atual
  • com extensão *. ext1 e *. ext2 ,
  • mas não name1. * ou name2. *

O comando a seguir funciona, mas pode não ser eficiente, porque o shell expande ./* e find pode obter uma lista enorme de arquivos e diretórios.

find ./* -prune \( -name '*ext1' -o -name '*ext2' \) -a ! \( -name 'name1*' -o -name 'name2*' \)

Atualização:

Estou trabalhando no AIX, não há opção -maxdepth .

    
por Mattia72 07.12.2016 / 08:45

4 respostas

3

com find :

find . ! -name . -prune \
    \( -name '*.ext1' -o -name '*.ext2' \) \
  ! \( -name 'name1.*' -o -name 'name2.*' \)

Usar -prune é o equivalente padrão do -maxdepth do GNU ou de -depth <n> do BSD (embora esses BSDs também suportem -mindepth / -maxdepth à GNU). Aqui, ele diz find para não descer em nenhum diretório, exceto . .

o ! -name . também exclui . da seleção, então ! -name . -prune é o equivalente padrão do -mindepth 1 -maxdepth 1 do GNU ou de alguns% BSDs -depth 1 . Para o -mindepth 1 do GNU (alguns BSDs ' -depth -2 ), você escreveria find . \( -name . -o -prune \) .

Com zsh , você também pode:

setopt extendedglob
printf '%s\n' *.(ext1|ext2)~(name1|name2).*(D)

~ sendo o operador não-e e (D) para incluir arquivos-ponto.

    
por 08.12.2016 / 18:33
2

No seu diretório atual, você pode usar ls com grep (supondo que seus nomes de arquivo não contenham caracteres de nova linha):

ls -a | grep -E '\.ext(1|2)$' | grep -vE '^name(1|2)\.'
    
por 07.12.2016 / 08:52
0

"Apenas no diretório atual" você não precisa de find arquivos, você pode simplesmente listá-los (com as advertências habituais sobre a possibilidade de encontrar nomes de arquivos bizarros, contendo caracteres interessantes):

ls -d *.ext1 *.ext2 2>/dev/null | grep -v '^\(name1\|name2\)\.'
    
por 07.12.2016 / 08:59
0

Como você tem disponível o bash, pode usar a correspondência de padrão estendido :

shopt -s extglob
files=( !(name1|name2).@(ext1|ext2) )

Isso diz: todos os arquivos no diretório atual que não começam com "name1" ou "name2", seguidos por um período, seguido por qualquer um "ext1 "ou" ext2 ".

Para uma amostra de corrida:

$ touch name1.ext1 name1.ext2 name2.ext1 name2.ext2 name3.ext1 name3.ext2 name3.ext3
$ files=( !(name1|name2).@(ext1|ext2) )
$ declare -p files
declare -a files='([0]="name3.ext1" [1]="name3.ext2")'

Observe que, se você tiver um nome de arquivo simples como "name3.ext2", terá que escolher onde colocar o período para a correspondência de padrões - em "name3". ou em ".ext2"; Se você tem nomes de arquivos mais longos, como "name3.intermediate.ext2", então você pode usar pontos e um glob no meio:

$ files=( !(name1|name2).*.@(ext1|ext2) )
    
por 08.12.2016 / 18:08