Come ottenere la dimensione effettiva della directory (fuori da du)?


17

Come posso ottenere le dimensioni effettive della directory, usando gli strumenti standard UNIX / Linux?

Domanda alternativa: come faccio a visualizzare du la dimensione effettiva della directory (non l'utilizzo del disco)?

Poiché le persone sembrano avere diverse definizioni del termine "dimensione": La mia definizione di "dimensione della directory" è la somma di tutti i file regolari all'interno di quella directory.

NON mi interessa la dimensione dell'inode della directory o qualunque cosa (blocchi * dimensione del blocco) i file occupino sul rispettivo file system. Una directory con 3 file, 1 byte ciascuno, ha una dimensione di directory di 3 byte (per definizione).

Il calcolo della dimensione della directory usando du sembra essere inaffidabile.
Ad esempio, mkdir foo && du -b fooriporta "4096 pippo", 4096 byte anziché 0 byte. Con directory molto grandi, la dimensione della directory indicata du -hspuò essere disattivata di almeno 100 GB (!) (File system compresso).

Quindi quale (strumento / opzione) deve essere usato per ottenere la dimensione effettiva della directory?


Quale filesystem viene utilizzato nella nuova posizione - è xfsper caso?
Sergey Vlasov,


E se il tuo nuovo FS è davvero XFS, l'utilizzo del disco notevolmente aumentato è probabilmente dovuto alla preallocazione aggressiva , che riduce la frammentazione dei file a costo dell'utilizzo del disco.
Sergey Vlasov,

Risposte:


8

Ecco uno script che mostra una dimensione di directory leggibile dall'uomo usando gli strumenti standard Unix (POSIX).

#!/bin/sh
find ${1:-.} -type f -exec ls -lnq {} \+ | awk '
BEGIN {sum=0} # initialization for clarity and safety
function pp() {
  u="+Ki+Mi+Gi+Ti+Pi+Ei";
  split(u,unit,"+");
  v=sum;
  for(i=1;i<7;i++) {
    if(v<1024) break;
    v/=1024;
  }
  printf("%.3f %sB\n", v, unit[i]);
}
{sum+=$5}
END{pp()}'

per esempio:

$ ds ~        
72.891 GiB

E ora ho trovato un'altra opzione che manca in tutte le proposte lsinvocazioni qui: -q. Senza questa opzione lo script si interromperà se il nome di un file contiene caratteri di nuova riga. Scrivere script di shell davvero affidabili è troppo difficile ...
Sergey Vlasov,

@SergeyVlasov Lo script che ho pubblicato non dovrebbe rompersi con tali file, semplicemente ignorando le righe extra. L'unico caso problematico si verificherebbe se un file creato con cura avesse una riga in più con il quinto colon che contiene un valore numerico. Il tuo suggerimento eviterebbe davvero quella situazione. Grazie per il suggerimento, script aggiornato.
jlliagre,

Risposta eccellente. +1 a te signore
ehime

Questa è una delle soluzioni più affidabili. Funziona con nomi di file che contengono spazi o virgolette e stampa una dimensione leggibile dall'uomo.
basic6,

@KIAaze Grazie per aver esaminato e corretto il mio codice!
jlliagre,

8

Alcune versioni dusupportano l'argomento --apparent-sizeper mostrare la dimensione apparente anziché l'utilizzo del disco. Quindi il tuo comando sarebbe:

du -hs --apparent-size

Dalle pagine man per du incluse in Ubuntu 12.04 LTS:

--apparent-size
      print apparent sizes,  rather  than  disk  usage;  although  the
      apparent  size is usually smaller, it may be larger due to holes
      in (`sparse') files, internal  fragmentation,  indirect  blocks,
      and the like

1
non funziona: segnala un po 'di spazio per le directory vuote
Karl Forner,

1
questo ha funzionato per me.
Connorbode,

2
Fornisce dimensioni significativamente diverse quando si confrontano directory su file system diversi. Ad esempio, la stessa cartella ha una dimensione apparente di 290 GB sul file system zfs e 324 GB di exFat. Le soluzioni di cui sopra danno le stesse dimensioni.
Pixus.ru,

4

Solo un'alternativa, usando ls:

ls -nR | grep -v '^d' | awk '{total += $5} END {print total, "Total"}'

ls -nR: -nlike -l, ma elenca UID e GID numerici ed -Relenca le sottodirectory ricorsivamente.

grep -v:Invertire il senso della corrispondenza, per selezionare linee non corrispondenti. (-v è specificato da POSIX.). '^ d'escluderà le directory.

Comando Ls: http://linux.about.com/od/commands/l/blcmdl1_ls.htm

Man Grep: http://linux.die.net/man/1/grep

MODIFICA :

Modificato come suggerimento @ Sergey Vlasov.


L'uso -ndell'opzione per lsinvece di -l(mostra numeri UID / GID anziché nomi) è più sicuro, poiché i nomi utente e gruppo possono contenere spazi (ad esempio, se winbindo sssdviene utilizzato per unire il sistema a un dominio Windows, è possibile ottenere nomi di gruppi come domain users) . Dovrebbe anche essere più veloce perché non è necessario cercare i nomi di utenti e gruppi.
Sergey Vlasov,

Grazie, è MOLTO più veloce di trovare -exec ls!
gpothier,

4

Supponendo che tu abbia duda GNU coreutils, questo comando dovrebbe calcolare la dimensione apparente totale del numero arbitrario di file regolari all'interno di una directory senza limiti arbitrari sul numero di file:

find . -type f -print0 | du -scb --files0-from=- | tail -n 1

Aggiungi l' -lopzione duse ci sono alcuni file hardlink all'interno e vuoi contare ogni hardlink separatamente (per impostazione predefinita duconta più hardlink solo una volta).

La differenza più importante con plain du -sbè che ricorsivo duconta anche dimensioni di directory, che sono riportate in modo diverso da diversi filesystem; per evitare ciò, il findcomando viene utilizzato per passare solo i file regolari a du. Un'altra differenza è che i collegamenti simbolici vengono ignorati (se devono essere contati, il findcomando deve essere modificato).

Questo comando consumerà anche più memoria del semplice du -sb, perché l'utilizzo del dispositivo --files0-from=FILErende dustore e inode i numeri di tutti i file elaborati, al contrario del comportamento predefinito di ricordare solo i file con più di un collegamento reale. (Questo non è un problema se l' -lopzione viene utilizzata per contare più volte i collegamenti fissi, poiché l'unico motivo per memorizzare i numeri di dispositivo e inode è quello di saltare i file con collegamenti fissi che erano già stati elaborati.)

Se vuoi ottenere una rappresentazione leggibile dall'uomo della dimensione totale, aggiungi semplicemente l' -hopzione (funziona perché duviene invocata una sola volta e calcola la dimensione totale stessa, a differenza di altre risposte suggerite):

find . -type f -print0 | du -scbh --files0-from=- | tail -n 1

o (se sei preoccupato che alcuni effetti di -bvengano quindi annullati da -h)

find . -type f -print0 | du -sc --apparent-size -h --files0-from=- | tail -n 1

Non sono sicuro di cosa fare per FreeBSD - anche se -bprobabilmente potrebbe essere sostituito da -A -B 1, non ci sono equivalenti per --files0-from=-, e l'utilizzo xargsrichiederà alcune soluzioni alternative nel caso in cui l'elenco dei file sia più grande di ARG_MAX(e qualche soluzione esterna per l'output leggibile dall'uomo).
Sergey Vlasov,

3

Se tutto ciò che desideri è la dimensione dei file, escludendo lo spazio occupato dalle directory, potresti fare qualcosa del genere

find . -type f -print0 | xargs -0 du -scb | tail -n 1

@SergeyVlasov ha sottolineato che ciò non funzionerà se si dispone di più file di argmax. Per evitare che tu possa usare qualcosa come:

find . -type f -exec du -sb '{}' \; | gawk '{k+=$1}END{print k}'

1
Questo comando fornirà silenziosamente un risultato errato se la directory contiene così tanti file che non rientrano nel limite della dimensione degli argomenti execve () - in questo caso xargsinvocherà dupiù volte e ogni invocazione stamperà il totale generale solo per parte sua dell'elenco completo dei file, quindi tailmostrerà solo la dimensione totale dell'ultima parte.
Sergey Vlasov,

1
@SergeyVlasov buon punto, non ci avevo pensato, grazie, risposta aggiornata.
terdon,
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.