Criando uma lista * bem formatada * do número de arquivos nos diretórios - awk & sed provavelmente

1

Eu tenho muitos e muitos arquivos em uma série de diretórios, e gostaria de uma lista bem formatada de quantos arquivos estão em cada diretório.

Os diretórios são ordenados assim: Diretórios pai denominados A, B, ... H, I. Sob cada um desses, há de 1 a 7 diretórios denominados 001, 002, ... 007. Nesses diretórios, Eu gostaria de contar os arquivos.

O que eu espero é algo assim:

...
C/003    122
C/004     45
C/005    462
D/001    215
E/001     98
E/002    323
...

Estou pensando em uma guia entre nome do diretório e contagem. Não importa se a contagem é justificada à esquerda ou à direita.

O que eu fiz sozinho é basicamente isso:

( for i in */*
do
  echo ">>> $i"
  ls "$i" | wc
done ) > file_count

O resultado é algo assim:

...
>>> F/002
  30   30   234
>>> F/003
  120  120  1322
>>> G/001
  78   78   620
...

Obviamente, nada mal ... e se eu substituí wc por wc -l e removi o "> > >" seria ainda melhor - exceto que cada "registro" seria mais de duas linhas em vez de uma.

Então, o que eu preciso é de alguma awk ou sed (ou qualquer que seja - existe uma ferramenta mais simples para unir duas linhas do que essas duas?) mágica para unir as duas e duas linhas em uma.

No entanto, se houver uma abordagem mais direta (shell-script, perl, python, algum realmente escuro sed & awk magic) que poderia fazer uma lista em "uma vez", isso seja ainda melhor ...

    
por Baard Kopperud 28.08.2015 / 16:12

5 respostas

2

Supondo que seus nomes de arquivo não contenham caracteres de nova linha e seu grep suporta a opção -o:

find [[:upper:]] -type f | grep -Eo '^./[0-9]{3}' | sort | uniq -c
    
por 28.08.2015 / 17:15
0

Você pode criar uma matriz de arquivos para cada diretório separadamente e, em seguida, apenas contar o número de elementos. Em bash , isso seria algo como

for dir in */*/; do a=( "$dir"/* ); printf "%s\t%s\n" "$dir:" "${#a[@]}"; done

Se A/001 etc. contiver diretórios também que conteúdo você gostaria de incluir, adicione ** glob:

shopt -s globstar
for dir in */*/; do a=( "$dir"/**/* ); printf "%s\t%s\n" "$dir:" "${#a[@]}"; done
    
por 28.08.2015 / 16:25
0

A maneira mais simples de obter o que você deseja é usar a opção -n para echo ao imprimir o nome do diretório. Isso evita imprimir uma nova linha no final do que você está fazendo eco, então a próxima saída permanece na mesma linha. Outros idiomas podem ser uma opção melhor se você quiser coletar as informações que está procurando e, em seguida, executar várias transformações antes de fornecer a saída.

    
por 28.08.2015 / 16:38
0

Isso fará o que você pediu:

for d in */*
do
    n=$(find "$d" -maxdepth 1 -type f -printf "ok\n" | wc -l)
    printf "%s\t%d\n" "$d" $n
done

As principais diferenças para o seu código são que usei find em vez de ls para que arquivos com nomes estranhos não quebrem a contagem (pense em \n em um nome de arquivo), e que eu tenha usou printf para formatar a saída.

    
por 28.08.2015 / 17:12
0

Talvez algo como:

find $PWD/ -type f -printf "%h\n
  7 /foo
 17 /foo/bar
  9 /foo/baz
" | uniq -zc

Renda algo como:

find $PWD/ -type f -printf "%h\n
  7 /foo
 17 /foo/bar
  9 /foo/baz
" | uniq -zc

Adicione um | sort -z antes de | uniq para classificá-lo.

    
por 28.08.2015 / 17:07