Como `du` apenas o espaço usado por arquivos que não estão vinculados em outro lugar?


14

Usando rsync --link-destpara capturas instantâneas de economia de espaço , como posso descobrir quanto espaço realmente economizei? Ou mais geral:

Como descobrir quanto espaço um diretório usa, considerando apenas arquivos que não estão vinculados em outro local fora da estrutura de diretórios? Perguntado de forma diferente: quanto espaço seria realmente liberado após a exclusão desse diretório? ( du -hsmentiria. O espaço necessário para os próprios hardlinks pode ser incluído)


2
Por padrão, o GNU duconta apenas os tamanhos de arquivo uma vez, mesmo se eles estiverem vinculados, a menos que você use a opção -l/ --count-links. Você executa dua árvore inteira duas vezes, com e sem essa opção e a diferença entre os tamanhos deve ser a quantidade de espaço que você salvou em todos os diretórios.
Jw013 25/10/12

Respostas:


9

Supondo que não haja links físicos internos (ou seja, todo arquivo com mais de um link físico esteja vinculado de fora da árvore), você pode:

find . -links -2 -print0 | du -c --files0-from=-

EDIT E aqui está o que eu esboçado no comentário, aplicado. Somente sem du; parabéns a @StephaneChazelas para perceber que dunão é necessário. Explicação no final.

( find . -type d -printf '%k + ' ; \
  find . \! -type d -printf '%n\t%i\t%k\n' | \
    sort | uniq -c                         | \
    awk '$1 >= $2 { print $4 " +\\" }' ; \
  echo 0 ) | bc

O que fazemos é criar uma string com o uso do disco (em KB) de cada arquivo relevante, separado por sinais de adição. Então alimentamos essa grande adição a bc.

A primeira findchamada faz isso para diretórios.

A segunda findimprime a contagem de links, o inode e o uso do disco. Passamos essa lista sort | uniq -cpara obter uma lista de (número de aparências na árvore, contagem de links, inode, uso do disco).

Passamos essa lista awke, se o primeiro campo (número de aparências) for maior ou igual ao segundo (número de hardlinks), o que significa que não há links para esse arquivo de fora da árvore e imprima o quarto campo ( uso de disco) com um sinal de adição e uma barra invertida anexada.

Finalmente, produzimos a 0, portanto a fórmula está sintaticamente correta (seria en +caso contrário) e a passamos para bc. Ufa.

(Mas eu usaria o primeiro método mais simples, se ele der uma resposta boa o suficiente.)


Obrigado, sim, se esse requisito for cumprido, ele funciona. Mas e se não for?
Tobias Kienzler 25/10/12

Isso não funciona, pois falha em explicar o tamanho dos próprios diretórios (que normalmente têm pelo menos 2 links e, se não tivessem, você teria arquivos contados duas vezes).
Stéphane Chazelas

1
Então seria necessário usar findpara imprimir uma lista de todos os arquivos com seus inodes e contagem de links; então, uma combinação de sort | uniq -cpara obter quantas vezes cada inode aparece na árvore, filtrar aqueles com contagem de links maior que o número de aparências ... e depois alimentar essa lista du. Mas se o requisito for atendido, salve o esforço.
angus

@StephaneChazelas Funciona, mas é verdade que não é responsável pelo tamanho do diretório. Se ao menos dutivesse um -dparâmetro parecido com lso da ...
angus 25/10

Observe também que, nos btrfssistemas de arquivos, o número de links para diretórios é sempre 1, portanto, você deve adicionar um! -type d
Stéphane Chazelas 25/12/12

5

Basicamente, você precisa obter os números de inode e o número de links para todos os arquivos (não diretórios), comparar esse número de link com o número de ocorrência de cada inode e, se eles diferirem, excluir o arquivo.

Supondo que todos estejam no mesmo sistema de arquivos, algo como isto deve funcionar (com o GNU find):

find . -type d -printf '%k\n' -o -printf '%i %n %k\n' |
   awk '
     NF==1{t+=$0; next}
     {n1[$1]=$2; n2[$1]++; s[$1]=$3}
     END {
       for (i in n1)
         if (n1[i] == n2[i])
           t+=s[i]
       print t
     }'

Sim, o que eu disse (obrigado pelo crédito). Mas, com a precisão extra obtida pela contagem de diretórios, você perde adicionando um uso inexato do disco.
angus

@angus, o que você quer dizer com "uso inexato de disco"?
Stéphane Chazelas

Nada, eu estava totalmente enganado sobre o que foi %krelatado. Isso é ótimo, dunão é necessário! Vou atualizar minha resposta quando chegar em casa. Obrigado!
angus

3

du na verdade não mentirá;) Analisa o (s) diretório (s) fornecido (s), contando apenas o primeiro de todos os hardlinks apontando para o mesmo inode encontrado.

Se você perguntar duo que vê apenas em um diretório, não importa se existem outros links físicos apontando para o mesmo conteúdo:

$ du -h daily.0 && du -hc daily.1
29G /daily.0
29G /daily.1

Agora forneça diretórios na mesma linha (começando pelo mais recente para backups incrementais do rsync com --link-dest):

$ du -hc daily.0 daily.1
29G /daily.0
364M /daily.1
29G total

Ou todo o diretório de backup:

$ du -hc --max-depth=1 /snapshots
29G /daily.0
364M /daily.1
537M /daily.2
333M /daily.3
30G total

Qualquer arquivo em 'daily.1' referenciando um inode (também conhecido como arquivo "real") já mencionado em 'daily.0' não será contado.

Portanto, excluir daily.1 economizará 364 MB no seu dispositivo.

RETIRAR

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.