Znajdź wszystkie pliki bez bajtów w katalogu i podkatalogach

82

Jak mogę znaleźć wszystkie pliki o rozmiarze zerowym w katalogu i jego podkatalogach?

Ja to zrobiłem:

#!/bin/bash
lns=`vdir -R *.* $dir| awk '{print $8"\t"$5}'`
temp=""
for file in $lns; do
    if test $file = "0"; then
        printf $temp"\t"$file"\n"
    fi
    temp=$file
done

Ale wyniki otrzymuję tylko w bieżącym katalogu, a nie w podkatalogach, a jeśli jakakolwiek nazwa pliku zawiera spację, otrzymuję tylko pierwsze słowo, po którym następuje tab

Civa
źródło
1
Możesz przeczytać man find.
alk
1
Pytanie również opublikowane na unix i linux - prosimy nie publikować tego samego pytania w wielu miejscach.
glenn jackman
Następnym razem nie będę się powtarzał w ten sposób z powodu problemu w mojej przeglądarce z przepełnieniem stosu, który opublikowałem w superużytkowniku, ale teraz problem został rozwiązany przez wyczyszczenie plików cookie historii i przechwycenie w ie, więc zapytałem ponownie tutaj
Civa

Odpowiedzi:

174

Aby wydrukować nazwy wszystkich plików w $ dir i poniżej o rozmiarze 0:

find "$dir" -size 0

Zwróć uwagę, że nie wszystkie implementacje finddomyślnie będą generować dane wyjściowe, więc może być konieczne wykonanie:

find "$dir" -size 0 -print

Dwie uwagi na temat ostatniej pętli w pytaniu:

Zamiast iterować po każdym innym słowie w ciągu i sprawdzać, czy wartości alternatywne są równe zero, możesz częściowo wyeliminować problem z białymi znakami, wykonując iterację po liniach. na przykład:

printf '1 f1\n0 f 2\n10 f3\n' | while read size path; do
    test "$size" -eq 0 && echo "$path"; done

Zauważ, że to się nie powiedzie w twoim przypadku, jeśli którakolwiek ze ścieżek wyjściowych ls zawiera znaki nowej linii, a to wzmacnia 2 punkty: nie analizuj ls znaki i miej rozsądną politykę nazewnictwa, która nie zezwala na spacje w ścieżkach.

Po drugie, aby wyprowadzić dane z pętli, nie ma potrzeby zapisywania danych wyjściowych w zmiennej tylko do echoniej. Jeśli po prostu pozwolisz pętli zapisać swoje wyjście na stdout, osiągniesz to samo, ale unikniesz przechowywania go.

William Pursell
źródło
czy mogę filtrować katalog inny niż * .xml
Civa
2
Jest też wygodna -emptyopcja.
Wesley Baugh
@WesleyBaugh z opcją -empty otrzymujesz również katalogi z zerowymi plikami w środku
Igor Scabini
1
@IgorScabini Jeśli chcesz ograniczyć się do plików, możesz to zrobić za pomocą -type f.
Wesley Baugh,
Śliczny! Prosto i do rzeczy. Człowieku, nie używam tego findpolecenia wystarczająco. Naprawdę muszę się pozbyć strachu przed zrozumieniem tego. Tak przydatne.
racl101
32

Jako dodatek do powyższych odpowiedzi:

Jeśli chcesz usunąć te pliki

find $dir -size 0 -type f -delete
LinuxLuigi
źródło
1
nie jest konieczne ciągłe usuwanie całego pliku o rozmiarze 0.
Raghvendra
następnie jak usunąć plik w folderze o rozmiarze 0
Raghvendra,
-exec /bin/rm {} \;lub -exec /bin/rm {} +będzie działać również na findimplementacjach innych niż GNU , które nie obsługują niestandardowego rozszerzenia-delete
Gert van den Berg
8

Nie, nie musisz zawracać sobie głowy grepem.

find $dir -size 0 ! -name "*.xml"
Batcher
źródło
3

Przetestowano Bash 4+ - to poprawny sposób wyszukiwania rozmiaru 0:

find /path/to/dir -size 0 -type f -name "*.xml"

Wyszukaj wiele rozszerzeń plików o rozmiarze 0:

find /path/to/dir -size 0 -type f \( -iname \*.css -o -iname \*.js \)

Uwaga: jeśli usuniesz \ (... \), wynikiem będą wszystkie pliki, które spełniają to wymaganie, a zatem rozmiar 0 zostanie zignorowany.

Mike Q
źródło
-inamenie jest przenośny do niektórych implementacji innych niż GNU. findZobacz tutaj listę standardowych opcji
Gert van den Berg