Eu gostaria de encontrar o maior arquivo em cada diretório recursivamente

6

A saída incluiria o nome do diretório, o nome do arquivo e o tamanho do arquivo. Um (maior arquivo) para cada diretório de onde o comando é executado.

Se possível, o tamanho médio dos arquivos nesse diretório também.

O objetivo é que os diretórios possam procurar arquivos que sejam muito maiores do que os outros no diretório, para que possam ser substituídos

    
por Derek 18.04.2017 / 09:24

5 respostas

8

A combinação de find e awk permite que as médias também sejam calculadas:

find . -type f -printf '%s %h/%f
BEGIN { RS="
printf "%.2f %d %s: %s\n", SUMSIZES[DIR] / NBFILES[DIR], MAXSIZE[DIR], DIR, BIGGESTFILE[DIR]
" } { SIZE=$1 for (i = 1; i <= NF - 1; i++) $i = $(i + 1) NF = NF - 1 DIR=$0 gsub("/[^/]+$", "", DIR) FILE=substr($0, length(DIR) + 2) SUMSIZES[DIR] += SIZE NBFILES[DIR]++ if (SIZE > MAXSIZE[DIR] || !BIGGESTFILE[DIR]) { MAXSIZE[DIR] = SIZE BIGGESTFILE[DIR] = FILE } } END { for (DIR in SUMSIZES) { printf "%s: average %f, biggest file %s %d\n", DIR, SUMSIZES[DIR] / NBFILES[DIR], BIGGESTFILE[DIR], MAXSIZE[DIR] } }
'|awk 'BEGIN { RS="
find . -type f -printf '%s %h/%f
BEGIN { RS="
printf "%.2f %d %s: %s\n", SUMSIZES[DIR] / NBFILES[DIR], MAXSIZE[DIR], DIR, BIGGESTFILE[DIR]
" } { SIZE=$1 for (i = 1; i <= NF - 1; i++) $i = $(i + 1) NF = NF - 1 DIR=$0 gsub("/[^/]+$", "", DIR) FILE=substr($0, length(DIR) + 2) SUMSIZES[DIR] += SIZE NBFILES[DIR]++ if (SIZE > MAXSIZE[DIR] || !BIGGESTFILE[DIR]) { MAXSIZE[DIR] = SIZE BIGGESTFILE[DIR] = FILE } } END { for (DIR in SUMSIZES) { printf "%s: average %f, biggest file %s %d\n", DIR, SUMSIZES[DIR] / NBFILES[DIR], BIGGESTFILE[DIR], MAXSIZE[DIR] } }
'|awk 'BEGIN { RS="%pre%" } { SIZE=$1; for (i = 1; i <= NF - 1; i++) $i = $(i + 1); NF = NF - 1; DIR=$0; gsub("/[^/]+$", "", DIR); FILE=substr($0, length(DIR) + 2); SUMSIZES[DIR] += SIZE; NBFILES[DIR]++; if (SIZE > MAXSIZE[DIR] || !BIGGESTFILE[DIR]) { MAXSIZE[DIR] = SIZE; BIGGESTFILE[DIR] = FILE } }; END { for (DIR in SUMSIZES) { printf "%s: average %f, biggest file %s %d\n", DIR, SUMSIZES[DIR] / NBFILES[DIR], BIGGESTFILE[DIR], MAXSIZE[DIR] } }'
" } { SIZE=$1; for (i = 1; i <= NF - 1; i++) $i = $(i + 1); NF = NF - 1; DIR=$0; gsub("/[^/]+$", "", DIR); FILE=substr($0, length(DIR) + 2); SUMSIZES[DIR] += SIZE; NBFILES[DIR]++; if (SIZE > MAXSIZE[DIR] || !BIGGESTFILE[DIR]) { MAXSIZE[DIR] = SIZE; BIGGESTFILE[DIR] = FILE } }; END { for (DIR in SUMSIZES) { printf "%s: average %f, biggest file %s %d\n", DIR, SUMSIZES[DIR] / NBFILES[DIR], BIGGESTFILE[DIR], MAXSIZE[DIR] } }'

Apresentado de uma maneira mais legível, o script AWK é

%pre%

Isso espera registros de entrada separados por nulo (eu roubei isso da resposta do muru ); para cada registro de entrada,

  • armazena o tamanho (para uso posterior),
  • remove tudo antes do primeiro caractere no caminho (para que possamos, pelo menos, manipular nomes de arquivos com espaços corretamente),
  • extrai o diretório
  • extrai o nome do arquivo,
  • adiciona o tamanho que armazenamos anteriormente à soma dos tamanhos no diretório
  • incrementa o número de arquivos no diretório (para que possamos calcular a média),
  • se o tamanho for maior que o tamanho máximo armazenado para o diretório ou se ainda não tivermos visto um arquivo no diretório, atualizará as informações do arquivo maior.

Depois de tudo isso, o script faz um loop sobre as chaves em SUMSIZES e gera o diretório, o tamanho médio, o nome e o tamanho do arquivo maior.

Você pode canalizar a saída em sort para classificar por nome de diretório. Se você deseja formatar adicionalmente os tamanhos de forma amigável, você pode alterar a linha printf para

%pre%

e, em seguida, canaliza a saída para numfmt --field=1,2 --to=iec . Você ainda pode classificar o resultado por nome de diretório, você só precisa classificar começando com o terceiro campo: sort -k3 .

    
por 18.04.2017 / 10:09
11

Com o GNU find , sort e sed (4.2.2 ou superior), classifique uma vez nos tamanhos de arquivo e novamente nos caminhos de diretório:

find /some/dir -type f -printf '%s %f%h
find /some/dir -type f -printf '%s %f%h
$ find /var/log -type f -printf '%s %f%h
find /some/dir -type f -printf '%s %f%h
find /some/dir -type f -printf '%s %f%h
$ find /var/log -type f -printf '%s %f%h%pre%' | sort -zrn | sort -zt/ -uk2 | sed -zre 's: ([^/]*)(/.*): /:' | tr '%pre%' '\n'
3090885 /var/log/syslog.1
39789 /var/log/apt/term.log
3968 /var/log/cups/access_log.1
31 /var/log/fsck/checkroot
467020 /var/log/installer/initial-status.gz
44636 /var/log/lightdm/seat0-greeter.log
15149 /var/log/lxd/lxd.log
4932 /var/log/snort/snort.log
3232 /var/log/unattended-upgrades/unattended-upgrades-dpkg.log
' | sort -zrn | sort -zut/ -k2 | sed -zre 's: ([^/]*)(/.*): /:' | tr '%pre%' '\n'
' | sort -zrn | sort -zut/ -k2 | sed -zre 's: ([^/]*)(/.*): /:'
' | sort -zrn | sort -zt/ -uk2 | sed -zre 's: ([^/]*)(/.*): /:' | tr '%pre%' '\n' 3090885 /var/log/syslog.1 39789 /var/log/apt/term.log 3968 /var/log/cups/access_log.1 31 /var/log/fsck/checkroot 467020 /var/log/installer/initial-status.gz 44636 /var/log/lightdm/seat0-greeter.log 15149 /var/log/lxd/lxd.log 4932 /var/log/snort/snort.log 3232 /var/log/unattended-upgrades/unattended-upgrades-dpkg.log
' | sort -zrn | sort -zut/ -k2 | sed -zre 's: ([^/]*)(/.*): /:' | tr '%pre%' '\n'
' | sort -zrn | sort -zut/ -k2 | sed -zre 's: ([^/]*)(/.*): /:'

Explicação:

  • O tamanho, o nome e o caminho do arquivo são impressos (o primeiro separado por um espaço e os dois seguintes separados por / ) e cada entrada é terminada pelo caractere ASCII NUL.
  • Em seguida, classificamos numericamente usando o tamanho, assumindo a saída delimitada por NUL (e na ordem inversa, para os arquivos maiores primeiro).
  • Em seguida, usamos sort para imprimir apenas as primeiras entradas exclusivas usando tudo do segundo campo / -separated, que seria o caminho para o diretório que contém o arquivo.
  • Em seguida, usamos sed para trocar o diretório e os nomes de arquivos, para que possamos obter um caminho normal.

Para uma saída legível, substitua o ASCII NUL por novas linhas:

%pre%

Exemplo de saída:

%pre%     
por 18.04.2017 / 09:58
3

Zsh 's Geração de nome de arquivo "> seriam muito úteis para o tipo de coisa que você está fazendo. Especificamente, o zsh pode corresponder arquivos por atributos como tipo, tamanho etc., por meio de qualificadores . Qualificadores Glob também permitem classificar os jogos.

Por exemplo, em zsh, *(.DOLN[1]) se expande para o nome do maior arquivo no diretório atual. * é o padrão para o nome do arquivo (corresponde a tudo, exceto possivelmente aos arquivos de ponto, dependendo das opções do shell). O qualificador . restringe as correspondências a arquivos regulares, D faz com que * inclua arquivos de ponto, OL ordene diminuindo o tamanho (“comprimento”), N faz com que a expansão fique vazia se não houver arquivo de correspondência, e [1] seleciona apenas a primeira correspondência.

Você pode enumerar diretórios recursivamente com **/ . Por exemplo, o seguinte loop itera sobre todos os subdiretórios do diretório atual e seus subdiretórios recursivamente:

for d in **/*(/); do … done

Você pode usar zstat para acessar o tamanho de um arquivo e outros metadados sem precisar depender de outras ferramentas para analisar.

zmodload -F zsh/stat b:zstat
files=(*(DNoL))
zstat -A sizes +size -- $files
total=0; for s in $sizes; do total+=$s; done
if ((#sizes > 0)); then
  max=$sizes[-1]
  average=$((total/#sizes))
  median=$sizes[$((#sizes/2))]
fi
    
por 19.04.2017 / 02:03
1

Esta é uma tentativa rápida

find . -type d | 
  while read dir; do 
    find "$dir" -maxdepth 1 -type f -printf '%12s %-30h %f\n' | 
      sort -nr | 
      head -1
  done |
  sort -k2
    
por 18.04.2017 / 09:44
0

Procure usar o baobab ou algum software semelhante, e provavelmente um ou mais deles estão incluídos na sua distribuição. Eles visualizam muito bem os diretórios do problema.

  • Baobab
  • JDiskReport
  • ncdu
  • K4DirStat
  • QDirStat
  • Mapa do GD

link

E a página man do baobab diz como é.

$> man baobab
BAOBAB(1)

NAME
       Baobab - A graphical tool to analyse disk usage

SYNOPSIS
       baobab  [directory]

DESCRIPTION
       baobab is able to scan either specific folders or the whole filesys-
       tem (local and remote), in order to give the user a graphical tree
       representation including each directory size or percentage in the
       branch.  It also auto-detects in real-time any change made to your
       home directory as far as any mounted/unmounted device. A graphical
       treemap window is also provided for any selected folder.

       A detailed documentation on the program could be read at:
       http://www.gnome.org/projects/baobab

AUTHOR
       Fabio MARZOCCA <[email protected]>



                                                                     BAOBAB(1)
    
por 18.04.2017 / 18:27

Tags