2009-08-24 20 views
7

Mam duży zestaw katalogów, dla których próbuję obliczyć sumę całkowitą kilkuset plików .txt. Próbowałem tego, co głównie działa:Dlaczego "find. -name * .txt | xargs du -hc" podaje wiele sum?

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

Ale zamiast dać mi jedną całość na końcu, otrzymuję kilka. Domyślam się, że rura będzie przekazywać tylko tyle wierszy wyników wyszukiwania na raz, a du po prostu działa na każdej partii, jaka nadejdzie. Czy istnieje sposób obejścia tego?

Dzięki! Alex

+0

Hm, ok. Próbowałem: znaleźć. -name * .txt | xargs -n 100000 du -hc Ale to nie działa - dostaję więcej subtotalów, nie mniej. Próbujesz znaleźć . -name * .txt | xargs -L 1000 du -hc "nie działa też dobrze. Albo "xargs: lista argumentów zbyt długa", albo działa tylko na bardzo niewielu plikach. Jakieś inne myśli? Dzięki! Alex –

Odpowiedz

11

Jak o użyciu --files0-z opcją du? Konieczne będzie odpowiednie wygenerowanie pliku wyjściowego z zakończeniem o wartości NULL:

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

działa poprawnie w moim systemie.

+0

Działa doskonale dla mnie! –

+2

ah, to działało dla mnie, ale użyłem find -print0 zamiast echa exec. – tladuke

+0

Hmm ... Nie wiedziałem o opcji -print0. To jest _co czystsze. Dzięki! – Sbodd

0

xargs wpycha swój wkład w porcje o rozsądnej wielkości - to, co widzisz, to sumy dla każdej z tych części. Sprawdź stronę man dla xargs na temat sposobów konfigurowania obsługi danych wejściowych.

3

Program xargs dzieli rzeczy na partie, aby uwzględnić ograniczenia wynikające z maksymalnej długości linii poleceń unix. Jest to jeszcze bardziej wydajne niż uruchamianie twojej podkomendy po jednej na raz, ale na długą listę danych wejściowych polecenie będzie uruchamiane wystarczająco długo, aby każde "uruchomienie" było wystarczająco krótkie, aby nie powodowało problemów.

Z tego powodu prawdopodobnie zobaczysz jedną linię wyjściową na "partię", którą xargs musi uruchomić.

Bo może okazać się przydatna ciekawe, strona/man można znaleźć w Internecie na: http://unixhelp.ed.ac.uk/CGI/man-cgi?xargs


Inną rzeczą, aby pamiętać (i może to być błąd w poście lub mój nieporozumienie) jest że masz "* .txt" bez komentarza. Czyli masz

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

gdzie prawdopodobnie chcesz

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

tą różnicą, że linia poleceń może być rozszerzanie * na listę nazw plików, które odpowiadają ... zamiast do przepuszczenia * znajdź, który użyje go jako wzorca.

0

Jednym z rozwiązań jest użycie alternate 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=- 

a jeśli chcesz mieć kilka różnych rozszerzeń, aby wyszukać go najlepiej zrobić:

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

Znacznie łatwiejsze do zapamiętania niż '-exec echo {}" = 0 ";'. nie, czekaj. To nie tak. Uhhh '-exec echo -n {}" \ 0 "\;'. Nie? '-exec echo $ # & @ * # (@! @ # $ @ # !!!' (O wiele lepiej) – Stephen

+0

Pierwszy z wymienionych sposobów nigdy nie dostanie się do testu '-iname * .txt' i globu' * .txt' rozwinie się zanim 'find' zostanie wykonany, jeśli pliki' .txt' znajdują się w twoim katalogu roboczym – BroSlow

+0

Masz rację Dziękujemy za wskazanie literówki Poprawiłem ją – OmnipotentEntity

3

Innym prostym rozwiązaniem:

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

Aby poprawić jakość twojego proszę podać, w jaki sposób/dlaczego twój post rozwiąże problem. –

0

Jedno rozwiązanie alternatywny jest użycie bash for pętla:

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

Jest to przydatne, gdy potrzebujesz większej kontroli nad tym, co dzieje się w pętli.