Contagem de entradas para cada diretório na árvore

1

Digamos que eu tenha a seguinte árvore:

root:
d foo 
d bar

/foo:
d A
- tmp.txt

/bar:
d B
- tmp2.txt

/foo/A:
- tmp3.txt

/bar/B:

d = diretório e - = arquivo

Eu preciso responder a seguinte pergunta: qual diretório (excluindo a raiz) contém menos entradas?

Eu tentei

  find . | grep -oE '/([a-zA-Z]+/)+'

para obter o número de ocorrências para cada diretório. O problema é que este comando exclui diretórios vazios, neste caso, a barra / B é excluída.

Qualquer orientação sobre como resolver isso seria apreciada.

    
por Carlj901 09.11.2013 / 17:14

2 respostas

5

Com ferramentas GNU:

find . -printf '%h
find . -printf '%h\n' -type d ! -name . -print | sort | uniq -c | sort -n | head -n1
' -type d ! -name . -print0 | sort -z | uniq -zc | sort -zn | sed -z q | tr '
count() {
  set -- $REPLY/*(NDoN)
  REPLY=$#
}
print -r -- **/*(Do+count[1])
' '\n'

Se você puder garantir que os nomes dos arquivos não conterão caracteres de nova linha, você poderá simplificá-lo para:

find . -printf '%h
find . -printf '%h\n' -type d ! -name . -print | sort | uniq -c | sort -n | head -n1
' -type d ! -name . -print0 | sort -z | uniq -zc | sort -zn | sed -z q | tr '
count() {
  set -- $REPLY/*(NDoN)
  REPLY=$#
}
print -r -- **/*(Do+count[1])
' '\n'

(o número informado é o número de arquivos no diretório menos 1 ( . é contado, mas não .. )).

com zsh :

%pre%     
por 09.11.2013 / 21:37
1

Você poderia usar algo assim:

find . -type d -exec sh -c \
    'printf -- "%-20s: " {};
    find {} -maxdepth 1 -type f -printf "%i\n" | wc -l' \;

Se você tem essa árvore, ( tree é um bom comando btw.):

$ tree -a .
.
├── bar
│   ├── B
│   └── tmp2.txt
├── ff
├── .ff.swp
└── foo
    ├── A
    │   └── tmp3.txt
    ├── f2.txt
    ├── f3.txt
    └── tmp.txt

Você consegue isso:

.                   : 2
./foo               : 3
./foo/A             : 1
./bar               : 1
./bar/B             : 0

Para listar um dos menores (mais do que um poderia ter, por exemplo, arquivos nulos), pode-se fazer algo como:

find . -type d -exec sh -c \
    'find "{}" -maxdepth 1 -type f -printf "%i\n" | \
    wc -l | xargs printf "%-2d";
    printf ": %s\n" "{}" ' \; | sort -k1,1 | head -n 1

se as pastas não contiverem nova linha.

Se -maxdepth não estiver disponível, uma alternativa poderia ser:

find . -type d -exec sh -c \
    'printf -- "%-20s: " "{}";
    find "{}" ! -wholename "{}" -prune -type f -printf "%i\n" | wc -l' \;
    
por 09.11.2013 / 19:55