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:)

Foi útil?

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]++ }'
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top