Come `du` solo lo spazio utilizzato dai file che non sono hardlinked altrove?


14

Utilizzando rsync --link-destper le istantanee salvaspazio , come posso capire quanto spazio ho effettivamente salvato? O più generale:

Come capire quanto spazio utilizza una directory considerando solo i file che non sono hardlink collegati altrove al di fuori della struttura della directory? Chiesto diversamente: quanto spazio verrebbe effettivamente liberato dopo una cancellazione di quella directory? ( du -hsmentirebbe. Lo spazio richiesto per gli hardlink stessi potrebbe essere incluso)


2
Per impostazione predefinita, GNU duconta le dimensioni dei file solo una volta anche se sono strettamente collegate a meno che non si usi l' opzione -l/ --count-links. Corri dusull'intero albero due volte, con e senza quell'opzione e la differenza tra le dimensioni dovrebbe essere la quantità di spazio che hai salvato su tutte le directory.
jw013,

Risposte:


9

Supponendo che non ci siano hardlink interni (ovvero, ogni file con più di 1 hardlink sia collegato dall'esterno dell'albero), puoi fare:

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

EDIT Ed ecco quello che ho abbozzato nel commento, applicato. Solo senza du; complimenti a @StephaneChazelas per aver notato che dunon è necessario. Spiegazione alla fine.

( 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

Quello che facciamo è creare una stringa con l'utilizzo del disco (in KB) di ogni file rilevante, separato da segni più. Quindi alimentiamo quella grande aggiunta a bc.

La prima findinvocazione lo fa per le directory.

Il secondo findstampa il conteggio dei collegamenti, l'inode e l'utilizzo del disco. Passiamo attraverso questo elenco sort | uniq -cper ottenere un elenco di (numero di aspetti nella struttura, conteggio dei collegamenti, inode, utilizzo del disco).

Passiamo che la lista attraverso awk, e, se il primo campo (numero di presenze) è maggiore o uguale al secondo (# di collegamenti fisici), il che significa che non ci sono link a questo file al di fuori della struttura, quindi stampare il quarto campo ( utilizzo del disco) con un segno più e una barra rovesciata allegata.

Alla fine produciamo a 0, quindi la formula è sintatticamente corretta ( +altrimenti sarebbe en ) e la passiamo a bc. Uff.

(Ma userei il primo metodo più semplice, se dà una risposta abbastanza buona.)


Grazie, sì, se tale requisito è soddisfatto, funziona. E se non lo fosse?
Tobias Kienzler,

Ciò non funziona poiché non riesce a tenere conto della dimensione delle directory stesse (che in genere hanno almeno 2 collegamenti e, in caso contrario, i file verranno conteggiati due volte).
Stéphane Chazelas,

1
Quindi sarebbe necessario utilizzare findper stampare un elenco di tutti i file con i loro inode e il conteggio dei collegamenti; quindi una combinazione di sort | uniq -cper ottenere quante volte ciascun inode appare nella struttura, quindi filtrare quelli con un numero di collegamenti maggiore del numero di apparizioni ... e quindi alimentare l'elenco du. Ma se il requisito è soddisfatto, meglio risparmiare lo sforzo.
angus,

@StephaneChazelas Funziona, ma è vero che non tiene conto delle dimensioni delle directory. Se solo duavesse un -dparametro simile a ls's ...
angus,

Nota anche che sui btrfsfilesystem il numero di collegamenti per le directory è sempre 1, quindi dovresti aggiungere un! -type d
Stéphane Chazelas,

5

Fondamentalmente, è necessario ottenere i numeri di inode e il numero di collegamenti per tutti i file (non directory), confrontare quel numero di collegamento con il numero di occorrenza di ciascun inode e, se diversi, escludere il file.

Supponendo che siano tutti sullo stesso filesystem, qualcosa del genere dovrebbe funzionare (con 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
     }'

Sì, quello che ho detto (grazie per il credito). Ma la precisione extra che ottieni contando le directory, perdi aggiungendo un uso del disco inesatto.
angus,

@angus, cosa intendi con "uso del disco inesatto"?
Stéphane Chazelas,

Niente, mi sbagliavo totalmente su quanto %kriportato. È fantastico, dunon è affatto necessario! Aggiornerò la mia risposta quando torno a casa. Grazie!
angus,

3

du in realtà non mentirà;) Analizza le dir che si danno, contando solo il primo di tutti i collegamenti fissi che puntano allo stesso inode che incontra.

Se chiedi ducosa vede in una sola directory, non gli importa che ci siano altri hard link che puntano allo stesso contenuto:

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

Ora assegnagli i dir sulla stessa riga (a partire da quello più recente per i backup incrementali rsync con --link-dest):

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

O l'intera directory di backup:

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

Qualsiasi file in 'daily.1' che fa riferimento a un inode (aka file "reale") già indicato in 'daily.0' non verrà conteggiato.

Pertanto, l'eliminazione giornaliera 1 consentirà di risparmiare 364 MB sul dispositivo.

RIMUOVERE

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.