Gostaria de encontrar o maior arquivo em cada diretório recursivamente

Gostaria de encontrar o maior arquivo em cada diretório recursivamente

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

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

O objetivo é fazer com que os diretórios procurem arquivos muito maiores que os demais no diretório para que possam ser substituídos

Responder1

Com GNU finde sort( sed4.2.2 ou superior), classifique uma vez pelos tamanhos dos arquivos e novamente pelos caminhos dos diretórios:

find /some/dir -type f -printf '%s %f%h\0' | 
  sort -zrn |
  sort -zut/ -k2 |
  sed -zre 's: ([^/]*)(/.*): \2/\1:'

Explicação:

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

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

find /some/dir -type f -printf '%s %f%h\0' | 
  sort -zrn |
  sort -zut/ -k2 |
  sed -zre 's: ([^/]*)(/.*): \2/\1:' |
  tr '\0' '\n'

Exemplo de saída:

$ find /var/log -type f -printf '%s %f%h\0' | sort -zrn | sort -zt/ -uk2 | sed -zre 's: ([^/]*)(/.*): \2/\1:' | tr '\0' '\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

Responder2

Combina finde awkpermite que as médias também sejam calculadas:

find . -type f -printf '%s %h/%f\0'|awk 'BEGIN { RS="\0" } { 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] } }'

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

BEGIN { RS="\0" }

{
  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]
  }
}

Isso espera registros de entrada separados por nulos (eu roubei isso deresposta de Muru); para cada registro de entrada,

  • armazena o tamanho (para uso posterior),
  • remove tudo antes do primeiro caractere no caminho (pelo menos tratamos 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,
  • aumenta 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 vimos um arquivo no diretório, atualiza as informações do arquivo maior.

Depois de tudo feito, o script percorre as chaves SUMSIZESe exibe o diretório, tamanho médio, nome e tamanho do maior arquivo.

Você pode canalizar a saída sortpara classificar por nome de diretório. Se desejar formatar adicionalmente os tamanhos de forma amigável, você pode alterar a printflinha para

printf "%.2f %d %s: %s\n", SUMSIZES[DIR] / NBFILES[DIR], MAXSIZE[DIR], DIR, BIGGESTFILE[DIR]

e, em seguida, canalize a saída para numfmt --field=1,2 --to=iec. Você ainda pode ordenar o resultado pelo nome do diretório, basta ordenar começando pelo terceiro campo: sort -k3.

Responder3

Zshdepadrões curingaseria muito útil para o tipo de coisas que você está fazendo. Especificamente, o zsh pode combinar arquivos por atributos como tipo, tamanho, etc.eliminatórias globais. As eliminatórias Glob também permitem classificar as partidas.

Por exemplo, em zsh, *(.DOLN[1])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, Dfaz com *que inclua arquivos de ponto, OLclassifica diminuindo o tamanho (“comprimento”), Nfaz com que a expansão fique vazia se não houver nenhum arquivo correspondente e [1]seleciona apenas a primeira correspondência.

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

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

Você pode usarzstatpara acessar o tamanho de um arquivo e outros metadados sem precisar depender de outras ferramentas para análise.

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

Responder4

Considere usar o baobab ou algum software semelhante, e um ou mais deles provavelmente estarão incluídos em sua distribuição. Eles visualizam muito bem os diretórios de problemas.

  • Baobá
  • Relatório JDisk
  • ncdu
  • K4DirStat
  • QDirStat
  • Mapa GD

http://alternativeto.net/software/baobab/?platform=linux

E a página de manual do baobab conta 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)

informação relacionada