Listar subdiretórios um nível abaixo que não contêm um determinado arquivo

6

Como posso encontrar todos os subdiretórios em um diretório (apenas 1 nível abaixo) que não contém um determinado arquivo?

    
por user196711 08.02.2013 / 16:58

2 respostas

5

Existem várias maneiras de conseguir isso com encontrar .

A abordagem 1 é menos hacky e funciona bem com nomes de diretórios estranhos (por exemplo, nomes de diretórios contendo novas linhas), mas a abordagem 2 deve ser mais rápida se houver muitos diretórios.

Abordagem 1

Comando

find DIR -type d -mindepth 1 -maxdepth 1 -not -exec test -f {}/FILENAME \; \
    -print | sort

Como funciona

  • find DIR -type d -mindepth 1 -maxdepth 1 localiza todos os diretórios ( -type d ) em DIR , com profundidade 1.

  • -not -exec test -f {}/FILENAME \; é verdadeiro se e somente se um arquivo chamado FILENAME não puder ser encontrado no diretório atualmente processado ( {} ).

  • -print produzirá os nomes de diretório desejados.

  • Se desejar, sort classificará a saída em ordem alfabética.

Abordagem 2

Comando

( find DIR -type f -mindepth 2 -maxdepth 2 -name FILENAME -printf "%h\n" ; \
    find DIR -type d -mindepth 1 -maxdepth 1 ) | sort | uniq -u

Como funciona

  • find DIR -type f -mindepth 2 -maxdepth 2 -name FILENAME encontra todos os arquivos ( -type f ) chamados FILENAME nos subdiretórios de DIR (arquivos de diretórios de profundidade 1 têm profundidade 2).

  • -print "%h\n" imprime os nomes dos diretórios que contêm arquivos nomeados FILENAME , seguidos por uma nova linha.

  • find DIR -type d -mindepth 1 -maxdepth 1 lista todos os diretórios ( -type d ) em DIR , com profundidade 1.

  • sort classifica a saída em ordem alfabética (a saída deve ser classificada quando o piping for uniq ).

  • uniq -u imprime apenas linhas exclusivas.

    Todo subdiretório DIR é listado pelo menos uma vez, mas aqueles que contêm um arquivo chamado FILENAME são listados duas vezes. uniq -u elimina o último tipo.

por 08.02.2013 / 17:19
1

Diretamente no script de shell:

for i in DIRECTORY/*/; do [ -f "$i/FILENAME" ] || basename "$i"; done
  • for i in DIRECTORY/*/ usa a expansão do shell para com segurança (não deve haver problemas com nomes de diretório estranhos) forneça todos os subdiretórios de um diretório específico. Observe a barra à direita para fornecer apenas os diretórios.
  • [ -f "$i/FILENAME" ] retornará verdadeiro se o arquivo denominado FILENAME existir no diretório nesta iteração. O operador || executa o seguinte comando se o primeiro retornar falso, ou seja, somente se o arquivo não existir no diretório.
  • basename "$i" imprime o nome do diretório (se o nome do arquivo não foi encontrado nele). Se você quiser o caminho completo e não apenas o nome do diretório, substitua basename por echo ou readlink -f ou outra coisa por preferência.

Se você também quiser incluir diretórios ocultos, execute (no Bash)

shopt -s dotglob

antes do comando.

    
por 08.02.2013 / 17:37

Tags