2009-08-24 19 views
7

Ho una vasta serie di directory per le quali sto cercando di calcolare la dimensione totale della somma di diverse centinaia di file .txt. Ho provato questo, che funziona principalmente:Perché "find. -name * .txt | xargs du -hc" fornisce più totali?

find . -name *.txt | xargs du -hc 

Ma invece di darmi un totale alla fine, ne ottengo diversi. La mia ipotesi è che la pipe trasmetterà solo così tante righe di output di find alla volta, e funziona solo su ogni batch così com'è. C'è un modo per aggirare questo?

Grazie! Alex

+0

Hm, ok. Ho provato: trovare . -name * .txt | xargs -n 100000 du -hc Ma quello non sembra funzionare - ottengo più subtotali, non meno. Cercando trovare. -name * .txt | xargs -L 1000 du -hc non sembra funzionare bene neanche. O "xargs: argument list too long" o funziona solo su pochissimi file. Qualche altro pensiero? Grazie! Alex –

risposta

11

ne dite di usare il --files0-da opzione per du? Dovresti generare il file con terminazione null in uscita in modo corretto:

find . -name "*txt" -exec echo -n -e {}"\0" \; | du -hc --files0-from=- 

funziona correttamente sul mio sistema.

+0

Funziona alla grande per me! –

+2

ah, questo ha funzionato per me, ma ho usato find's -print0 invece di exec echo stuff. – tladuke

+0

Hmm ... Non conoscevo l'opzione -print0. È molto più pulito. Grazie! – Sbodd

0

xargs inserisce il proprio input in blocchi di dimensioni ragionevoli: ciò che si vede sono i totali per ciascuno di questi blocchi. Controlla la pagina man per xargs su come configurare la sua gestione dell'input.

3

Il programma xargs suddivide le parti in lotti, per tenere conto dei limiti dovuti alla lunghezza massima di una riga di comando Unix. È ancora più efficiente di eseguire il sottocomando uno alla volta ma, per un lungo elenco di input, eseguirà il comando abbastanza volte che ogni "esecuzione" è sufficientemente breve da non causare problemi.

Per questo motivo è probabile che venga visualizzata una riga di output per "batch" che xargs deve eseguire.

Perché si può trovare interessante, la pagina utile/uomo può essere trovato on-line qui: http://unixhelp.ed.ac.uk/CGI/man-cgi?xargs


Un'altra cosa da notare (e questo può essere un errore di battitura nel tuo post o il mio equivoco) è che hai il "* .txt" senza escape/quotato. Vale a dire, avete

find . -name *.txt | xargs du -hc 

dove probabilmente si desidera

find . -name \*.txt | xargs du -hc 

La differenza è che la linea di comando può essere espandendo l'* nella lista di nomi di file che corrispondono ... piuttosto che passare il * in trova, che lo userà come modello.

0

Una soluzione alternativa è quella di utilizzare awk:

find . -name "*.txt" -exec ls -lt {} \; | awk -F " " 'BEGIN { sum=0 } { sum+=$5 } END { print sum }' 
7
find . -print0 -iname '*.txt' | du --files0-from=- 

e se si vuole avere diverse estensioni diverse per cercare è meglio fare:

find . -type f -print0 | grep -azZEi '\.(te?xt|rtf|docx?|wps)$' | du --files0-from=- 
+0

Molto più facile da ricordare di '-exec echo {}" = 0 ";'. non aspettare. Non è giusto. Uhhh '-exec echo -n {}" \ 0 "\;'. No? '-exec echo $ # & @ * # (@! @ # $ @ # !!!' (Molto meglio) – Stephen

+0

Il primo modo che hai elencato non arriverà mai al test '-iname * .txt' e al glob' * .txt' si espanderà prima che il 'find' venga eseguito se nella directory di lavoro sono presenti file' .txt'. – BroSlow

+0

Sei corretto. Grazie per aver segnalato l'errore di battitura. L'ho corretto. – OmnipotentEntity

3

Un'altra soluzione semplice:

find . -name *.txt -print0 | xargs -0 du -hc 
+1

Per migliorare la qualità del tuo post per favore includi come/perché il tuo post risolverà il problema. –

0

Una soluzione alternativa è quella di utilizzare bash for loop:

for i in `find . -name '*.txt'`; do du -hc $i | grep -v 'total'; done 

Ciò è utile quando è necessario un maggiore controllo su ciò che accade nel ciclo.