localiza todos os subdiretórios finais em uma árvore

10

dada a seguinte estrutura:

oz123@debian:~/ $ tree .
.
├── a
│   ├── a1
│   ├── a2
│   └── a3
├── a1
│   ├── a11
│   ├── a12
│   └── a31
├── b
│   └── b1
│       ├── b11
│       │   └── b21
│       │       └── b31
│       ├── b12
│       └── b3
└── c

16 directories, 0 files

Como encontro todos os nós finais?

Eu encontrei as seguintes soluções que parecem serem boas, mas eu tenho que provar que não há caso de teste que irá falhar.

A página de ajuda dos estados -links :

You can also search for files that have a certain number of links, with ‘-links’. Directories normally have at least two hard links; their . entry is the second one. If they have subdirectories, each of those also has a hard link called .. to its parent directory. The . and .. directory entries are not normally searched unless they are mentioned on the find command line.

possível solução:

oz123@debian:~/ $ find .  -type d  -links 2
./a/a2
./a/a3
./a/a1
./c
./a1/a31
./a1/a11
./a1/a12
./b/b1/b12
./b/b1/b3
./b/b1/b11/b21/b31
  • Alguém pode fornecer uma solução melhor (sem usar pipes e sed, isso tem desempenho ...)
  • Funcionará em qualquer sistema de arquivos?
por Oz123 12.08.2013 / 10:22

4 respostas

3

Como complemento à sua própria solução com -links , quero apenas acrescentar que ele não funcionará em sistemas de arquivos que não seguem a convenção de link de diretório Unix. De man find na opção -noleaf , estes são, pelo menos, CD-ROM, sistemas de arquivos MS-DOS e pontos de montagem de volume do AFS.

Para uma referência, esta questão já foi discutida com diferentes soluções que são realmente mais lentas e geralmente recorrem à canalização para sed / awk e similares.

por 12.08.2013 / 13:15
3

Há uma opção um pouco mais óbvia -empty :

find . -type d -empty

upd. Ok, você está certo assim não funciona com arquivos no diretório.

Então, aqui está uma versão não confiável do sistema de arquivos fixo:

find dtest/ -type d -exec sh -c "if [ \$(find {} -maxdepth 1 -type d | wc -l) -eq 1 ]; then echo {} ; fi" \;
    
por 12.08.2013 / 10:32
1

find . -type d -links 2 funciona na maioria dos sistemas de arquivos, mas não em todos. Não acho que haja uma maneira de saber além de saber quais tipos de sistema de arquivos têm a propriedade de que os diretórios contêm um link para eles mesmos. O GNU find detecta isto dinamicamente (se ele imprime algo sobre "Ativar automaticamente a opção -noleaf do find", você sabe que seu sistema de arquivos não possui essa propriedade). Os tipos mais comuns de sistemas de arquivos são ok, mas não FAT ou btrfs.

Se você quiser ter certeza, terá que testar cada diretório. Uma maneira de fazer isso é invocar find novamente para cada subdiretório.

find . -type d ! -exec sh -c '
   find "$1/." ! -name . -type d -prune | grep -q "^"' sh {} \; -print

(com GNU find , você pode substituir -prune por -print -quit para torná-lo um pouco mais eficiente).

Outra maneira é pós-processar a saída de find . Com find -depth , um diretório de folhas é aquele que não segue um subdiretório dele mesmo.

find . -depth -type d -print0 |
awk -v RS='
find . -type d ! -exec sh -c '
   find "$1/." ! -name . -type d -prune | grep -q "^"' sh {} \; -print
' ' substr(previous, 1, length($0) + 1) != $0 "/" { previous = $0 } '
    
por 13.08.2013 / 01:51
0

Tente a seguinte solução (deve ser compatível com Linux, Unix e OS X):

find . -type d -execdir sh -c 'test -z "$(find "{}" -mindepth 1 -type d)" && echo $PWD/{}' ';'

É uma abordagem semelhante à solução de urgência , mas sem canais.

    
por 23.09.2015 / 16:14