comando UNIX para listar pastas com contagens de arquivo
Pergunta
Eu quero começar uma lista de pastas no nível atual (não incluindo as suas subpastas) e simplesmente imprimir o nome da pasta e uma contagem do número de arquivos na pasta (de preferência de filtragem para * .jpg se possível).
Isso é possível no shell bash padrão? ls -l
impressões sobre tudo, mas a contagem de arquivos:)
Solução
Eu vim acima com este:
find -maxdepth 1 -type d | while read dir; do
count=$(find "$dir" -maxdepth 1 -iname \*.jpg | wc -l)
echo "$dir ; $count"
done
Gota a segunda -maxdepth 1
se a pesquisa dentro dos diretórios para arquivos JPG deve ser recursiva considerando sub-diretórios. Note que que considera apenas o nome dos arquivos. Você pode renomear um arquivo, escondendo que é uma imagem jpg. Você pode usar o comando file
para fazer um palpite sobre o conteúdo, em vez (agora, também procura recursivamente):
find -mindepth 1 -maxdepth 1 -type d | while read dir; do
count=$(find "$dir" -type f | xargs file -b --mime-type |
grep 'image/jpeg' | wc -l)
echo "$dir ; $count"
done
No entanto, isso é muito mais lento, uma vez que tem de ler parte dos arquivos e, eventualmente, interpretar o que eles contêm (se é sorte, ele encontra um ID de mágica no início do arquivo). Os impede -mindepth 1
-a de imprimir .
(o diretório atual) como outro diretório que ele procura.
Outras dicas
Eu encontrei esta pergunta depois que eu já tinha descoberto meu próprio script semelhante. Parece para atender às suas condições e é muito flexível, então eu pensei que eu iria adicioná-lo como uma resposta.
Vantagens:
- podem ser agrupados para
qualquer profundidade (0 para.
, um para subdirectórios primeiro nível, etc.) - impressões de saída muito
- não loop, e apenas um comando
find
, por isso é um pouco mais rápido em grandes diretórios - ainda pode ser ajustado para adicionar filtros personalizados (maxdepth para torná-lo não recursivo, nome do arquivo padrão)
Código Raw:
find -P . -type f | rev | cut -d/ -f2- | rev | \
cut -d/ -f1-2 | cut -d/ -f2- | sort | uniq -c
Envolvido em uma função e explicou:
fc() {
# Usage: fc [depth >= 0, default 1]
# 1. List all files, not following symlinks.
# (Add filters like -maxdepth 1 or -iname='*.jpg' here.)
# 2. Cut off filenames in bulk. Reverse and chop to the
# first / (remove filename). Reverse back.
# 3. Cut everything after the specified depth, so that each line
# contains only the relevant directory path
# 4. Cut off the preceeding '.' unless that's all there is.
# 5. Sort and group to unique lines with count.
find -P . -type f \
| rev | cut -d/ -f2- | rev \
| cut -d/ -f1-$((${1:-1}+1)) \
| cut -d/ -f2- \
| sort | uniq -c
}
Produz uma saída como esta:
$ fc 0
1668 .
$ fc # depth of 1 is default
6 .
3 .ssh
11 Desktop
44 Downloads
1054 Music
550 Pictures
É claro que com o primeiro número que pode ser canalizada para sort
:
$ fc | sort
3 .ssh
6 .
11 Desktop
44 Downloads
550 Pictures
1054 Music
meu é mais rápido digitar na linha de comando. :)
fazer as outras sugestões oferecer qualquer vantagem real sobre o seguinte?
find -name '*.jpg' | wc -l # recursive
find -maxdepth 1 -name '*.jpg' | wc -l # current directory only
#!/bin/bash
for dir in `find . -type d | grep -v "\.$"`; do
echo $dir
ls $dir/*.jpg | wc -l
done;
Você pode fazê-lo sem comandos externos:
for d in */; do
set -- "$d"*.jpg
printf "%s: %d\n" "${d%/}" "$#"
done
Ou você pode usar awk ( nawk ou / usr / XPG4 / bin / awk em Solaris ) :
printf "%s\n" */*jpg |
awk -F\/ 'END {
for (d in _)
print d ":",_[d]
}
{ _[$1]++ }'