Exclui todos os subdiretórios, exceto um caminho específico em um comando find

3

Eu uso um comando find para procurar todos os arquivos com uma determinada extensão nos subdiretórios atuais, ignorando determinado caminho do diretório:

find -L . \( -wholename "*/ignoredPath" -o -wholename "*/ignoredPath2" \) -prune -o -name "*.ext"

Isso está funcionando muito bem, mas agora quero ignorar outro caminho, exceto um subdiretório preciso. Como fazer isso sem listar todos os subdiretórios para ignorar?

Por exemplo, se eu tiver a seguinte árvore de pastas:

*/base/pathToIgnore1
*/base/subdir/requiredPath
*/base/subdir/pathToIgnore2
*/base/subdir/pathToIgnore3
*/base/pathToIgnore4

Como posso escrever o comando find ignorar todos os subdiretórios base , exceto o caminho */base/subdir/requiredPath ?

Eu tentei algo como

find -L . \( -wholename "*/ignoredPath" -o -wholename "*/ignoredPath2" -o \( -wholename "*/base" -a ! -wholename "*/base/subdir/requiredPath" \) \) -prune -o -name "*.ext"

Mas isso não funcionou, todos os subdiretórios base são ignorados.

    
por greydet 14.05.2013 / 09:59

2 respostas

1
find -L . \
  \( -type d \
    \( -path "*/ignore" -o -path "*/indeed" -o \
      \( -path "*/subdir/*" ! -path "*/subdir/save" \
      \) \
    \) \
  \) \
  -prune -o -print

Se você quiser um filtro extra (como -name "*.ext" ), você precisa colocar isso em branco antes de -print . A última parte, em seguida, parece com isso

  -prune -o \( -name "*.ext" \) -print

Note que alterei os nomes para facilitar a capacidade de escrita e a legibilidade. Nomes começando com i devem ser ignorados. Nomes começando com s devem ser mostrados. Nomes que terminam em file são arquivos.

Minha árvore é assim:

$ find -printf "%y %p\n"
d .
d ./base
d ./base/subdir
d ./base/subdir/inform
f ./base/subdir/inform/imagefile
d ./base/subdir/isolate
f ./base/subdir/isolate/individualfile
f ./base/subdir/whatwhatinthefile
d ./base/subdir/save
f ./base/subdir/save/soundfile
f ./base/superfile
d ./base/indeed
f ./base/indeed/itemfile
d ./base/show
f ./base/show/startfile
d ./base/ignore
f ./base/ignore/importantfile

A saída do comando acima:

.
./base
./base/subdir
./base/subdir/whatwhatinthefile
./base/subdir/save
./base/subdir/save/soundfile
./base/superfile
./base/show
./base/show/startfile

Observe que whatwhatinthefile em base/subdir . Se você não quiser os arquivos em base/subdir , precisará excluí-los explicitamente. Eu tentei, mas a linha de comando ficou feia demais.

Dependendo do seu caso de uso, pode ser mais fácil definir uma função de shell como esta:

contrivedfind() {
  find -L . \
    \( -type d \
      \( -path "*/ignore" -o -path "*/indeed" -o -path "*/subdir" \
      \) \
    \) \
    -prune -o -print
  find -L ./base/subdir/save
}

A saída é agora:

.
./base
./base/superfile
./base/show
./base/show/startfile
./base/subdir/save
./base/subdir/save/soundfile

A única outra coisa diferente de antes agora é a entrada ./base/subdir ausente. Mas acho que isso não importa no seu caso, porque você quer filtrar arquivos de qualquer maneira.

Como antes, você precisa colocar qualquer filtro extra antes do -print no primeiro find e desta vez também no final do segundo find .

    
por 14.05.2013 / 22:54
0

Você precisa impedir que */base seja correspondido:

Editar 1:

find -L . -type d \
  \( -wholename "*/ignoredPath" -o -wholename "*/ignoredPath2" -o \
  \( -wholename "*/base/*" -a \
  \( ! -wholename "*/base/subdir" -a ! -wholename "*/base/subdir/*" \) \) -o \
  \( -wholename "*/base/subdir/*" -a \
  \( ! -wholename "*/base/subdir/requiredPath" -a ! -wholename "*/base/subdir/requiredPath/*" \) \) \) \
  -prune -o -print

Isso é um pouco complicado: evita correspondências acidentais de diretórios como subdir2 , que provavelmente não existem. Mas você nunca sabe ...: -)

    
por 14.05.2013 / 12:46

Tags