2012-02-28 8 views
33

Tak więc, w wielu sytuacjach chciałem wiedzieć, ile przestrzeni dyskowej jest używane przez co, więc wiem, czego się pozbyć, przekonwertować na inny format, przechowywać gdzie indziej (np. DVD danych), przenieść się do innego partycja itp. W tym przypadku szukam partycji Windows z nośnika startowego SliTaz Linux.Wykorzystanie dysku plików, których nazwy pasują do wyrażenia regularnego, w systemie Linux?

W większości przypadków, co chcę jest rozmiar plików i folderów, a do tego używam ncurses oparte ncdu:

                                ncdu

Ale w tym przypadku chcę, aby uzyskać ze z wszystkie pliki pasujące do regex. Przykładem regex pliki .bak:

.*\.bak$ 

Jak mogę uzyskać te informacje, biorąc pod uwagę standardowe Linux z podstawowych narzędzi GNU lub BusyBox?

Edytuj: Dane wyjściowe mają być analizowane przez skrypt.

Odpowiedz

36

proponuję coś takiego: find . -regex '.*\.bak' -print0 | du --files0-from=- -ch | tail -1

Kilka uwag:

  • Opcja -print0 dla find i --files0-from dla du są tam, aby uniknąć problemów z białych znaków w nazwach plików
  • Wyrażenie regularne jest porównywana z całej ścieżce, na przykład./dir1/subdir2/file.bak, nie tylko file.bak, więc jeśli go zmodyfikować, wziąć to pod uwagę
  • użyłem h flagę du produkować format „Human czytelny”, ale jeśli chcesz analizować dane wyjściowe, może być lepiej z k (zawsze używać kilobajtów)
  • Jeśli usuniesz komendy tail, można dodatkowo zobaczyć rozmiary poszczególnych plików i katalogów

Sidenote: ładny narzędzie GUI do znajdowania się, kto zjadł swoją przestrzeń dyskowa jest FileLight. Nie robi wyrażeń regularnych, ale jest bardzo przydatny do znajdowania dużych katalogów lub plików zatykających twój dysk.

+2

+1, wygląda super! Co z '-s' dla' du'? Nie można sprawdzić teraz, ale wierzę, że 'du' może wyświetlać sumę całkowitą bez Potrzebuję 'tail' .To narzędzie FileLight przypomina Gnome's Disk Usage Analyzer.Wciąż jednak znajduję interfejs" details view-like "z aplikacji ncdu, o której wspomniałem w OP, ale jest on bardzo dobry :) (I ' ve już otwarty Disk Usage Analyzer sprawił, że ktoś pomyśli z tego przejrzystego interfejsu użytkownika, że ​​to, co robiłem, aby naprawić jego komputer, było bardziej skomplikowane niż to, co faktycznie było ... Działa! Hehe). –

+1

'-s' wyświetla sumę całkowitą dla każdego argumentu osobno - tutaj mamy wiele argumentów, dlatego' -c' jest opcją, której potrzebujemy. –

+0

Dzięki, sprawdzone i działa (ale nie z BusyBox "du", ponieważ nie obsługuje '--files0-from', więc zainstalowałem coreutils), więc przyjmuję to, ponieważ wydaje się nieszkodliwe dla terrorystów nazwy plików. –

3

Run to w Bourne Shell zadeklarować funkcję, która oblicza sumę wielkości wszystkich plików pasujących do wzorca wyrażenia regularnego w bieżącym katalogu:

sizeofregex() { IFS=$'\n'; for x in $(find . -regex "$1" 2> /dev/null); do du -sk "$x" | cut -f1; done | awk '{s+=$1} END {print s}' | sed 's/^$/0/'; unset IFS; } 

(Alternatywnie, można umieścić go w skrypcie).

Zastosowanie:

cd /where/to/look 
sizeofregex 'myregex' 

wynik będzie wiele (w kib), w tym 0 (jeśli nie ma plików pasujących do Twojego wyrażenia regularnego).

Jeśli nie chcesz go szukać w innych systemach plików (powiedzmy chcesz poszukać wszystkich .so plików w /, co jest mocowanie od /dev/sda1, ale nie pod /home, który jest mocowanie od /dev/sdb1, dodać -xdev . parametr find w funkcji powyżej

+0

Nie należy iteracyjne nad wynikami wyszukiwania za pomocą pętli for. Spowoduje to zerwanie, jeśli plik ma spacje. Użyj find -exec. Poza tym cut i sed nie będą potrzebne do sformatowania danych wyjściowych. awk może to wszystko zrobić. – jordanm

+0

@jordanm Przykro mi, zapomniałem o czymś, zaktualizuję. Gotowe. –

+0

Nadal całkiem hackish, nawet z zestawem IFS. Co jest złego w korzystaniu z find -exec? – jordanm

1

Jeśli jesteś OK z Glob-wzorców i jesteś zainteresowany tylko w bieżącym katalogu:

stat -c "%s" *.bak | awk '{sum += $1} END {print sum}' 

lub

sum=0 
while read size; do ((sum += size)); done < <(stat -c "%s" *.bak) 
echo $sum 

Dyrektywa %s do stat nie daje bajtów kilobajtów.

Jeśli chcesz zejść do podkatalogów, z bash w wersji 4, może shopt -s globstar i używać ty wzór **/*.bak

+0

+1 - wersja 4 jest wymaganą "ostatnią" wersją. – jordanm

+0

Tak więc w Bash 4 '**/*. Bak' oznacza pliki .bak w * dowolnym podkatalogu *? tj. nie tylko jeden katalog poniżej? –

+0

@CamiloMartin, poprawne. –

20

du jest moja ulubiona odpowiedź. Jeśli masz stałą strukturę systemu plików, można użyć:

du -hc *.bak 

jeśli trzeba dodać subdirs, wystarczy dodać:

du -hc *.bak **/*.bak **/**/*.bak 

etc etc

Jednakże, nie jest to bardzo przydatne polecenie, więc za pomocą twojego znalezienia:

TOTAL=0;for I in $(find . -name \*.bak); do TOTAL=$((TOTAL+$(du $I | awk '{print $1}'))); done; echo $TOTAL 

To będzie echo całkowitego rozmiaru w bajtach wszystkich znalezionych plików.

Nadzieję, że pomaga.

+0

to nie obsługuje wyrażeń regularnych –

+0

Ma ten sam problem, który zauważyłem przy innej odpowiedzi. Ponieważ katalogi mogą być nazwane "* .bak" du zarówno policzą pliki w katalogu o nazwie .bak, jak i cały katalog! Spowoduje to przekroczenie i podwójną liczbę (lub, co gorsza, jeśli masz zagnieżdżone katalogi .bak). –

3

Dotychczasowe rozwiązania nie działa prawidłowo dla mnie (miałem problemy orurowanie du), ale dodaje pracował wielki:

find path/to/directory -iregex ".*\.bak$" -exec du -csh '{}' + | tail -1 

Opcja iregex jest sprawa niewrażliwe wyrażenie regularne. Użyj opcji regex, jeśli chcesz, aby wielkość liter była rozróżniana.

Jeśli nie są wygodne z wyrażeń regularnych, można użyć iname lub name flagi (pierwszym przypadku człowiek niewrażliwy):

find path/to/directory -iname "*.bak" -exec du -csh '{}' + | tail -1 

W przypadku, gdy chcesz rozmiar każdym meczu (zamiast po prostu łączna), po prostu opuścić komendę rurami ogon:

find path/to/directory -iname "*.bak" -exec du -csh '{}' + 

podejścia te uniknąć podkatalogu problem w odpowiedzi @MaddHackers.

Mam nadzieję, że to pomoże innym w tej samej sytuacji (w moim przypadku, znalezienie rozmiaru wszystkich bibliotek DLL w rozwiązaniu .NET).

+1

Należy zauważyć, że '+' oznacza, że ​​'find' będzie starał się wywoływać komendę' du' tak mało, jak to tylko możliwe, poprzez dołączanie jak największej liczby trafień do pojedynczego wywołania 'du', jednak z powodu ograniczeń systemu (np. z dozwolonych argumentów), może nie być możliwe dołączenie wszystkich trafień do pojedynczego wywołania "du", a następnie podzieli je na wiele wywołań, co spowoduje niepoprawny wynik. – Mecki

+1

Aha, a ty zapomniałeś zacytować '* .bak'. W twojej próbce powłoka rozwinęłaby ją, ale chcesz 'find' ją rozwinąć, więc musisz użyć' "* .bak" '. Naprawię to dla ciebie. – Mecki

1

Przyjęty odpowiedź sugeruje użycie

find . -regex '.*\.bak' -print0 | du --files0-from=- -ch | tail -1 

ale to nie działa na moim systemie jako du nie wie --files-0-from opcję na moim systemie. Tylko GNU du zna tę opcję, nie jest ani częścią POSIX Standard (więc nie znajdziesz jej w FreeBSD ani macOS), ani nie znajdziesz go na BusyBox based Linux systems (np. Większość wbudowanych systemów Linux) ani w żadnym innym systemie Linux, który nie używa wersja GNU du.

Potem jest odpowiedź sugeruje używać:

find path/to/directory -iregex .*\.bak$ -exec du -csh '{}' + | tail -1 

Rozwiązanie to będzie działać tak długo, jak nie ma zbyt wiele plików znaleziono, jak + oznacza, że ​​find spróbuje zadzwonić du z tak wielu hitów, jak to możliwe w jednym wywołaniu może jednak istnieć maksymalna liczba argumentów (N) obsługiwanych przez system i jeśli jest więcej trafień niż ta wartość, find będzie wielokrotnie wywoływać du, dzieląc trafienia na grupy mniejsze lub równe N pozycji w tym przypadku wynik będzie nieprawidłowy i będzie wyświetlany tylko rozmiar ostatniego połączenia du.

Wreszcie jest odpowiedź przy użyciu stat i awk, co jest dobrym sposobem na to, ale opiera się na globowaniu powłoki w sposób, który obsługuje tylko Bash 4.x lub nowszy. Nie będzie działać ze starszymi wersjami i jeśli działa z innymi powłokami, jest nieprzewidywalny.

POSIX zgodne rozwiązanie (działa na Linux, MacOS oraz wszelkich wariantach BSD), że nie cierpi od jakichkolwiek ograniczeń i że na pewno działa z każdym skorupy byłoby:

find . -regex '.*\.bak' -exec stat -f "%z" {} \; | awk '{s += $1} END {print s}' 
+0

To jest świetny zapis, +1 - odkrycie o ograniczeniu liczby argumentów jest szczególnie ważne, ponieważ może dawać złe wyniki i doprowadzać kogoś do szaleństwa, dopóki nie wymyśli tego. –