Chcę usunąć wszystkie pliki zawierające ciąg foo
. Jak mogę to zrobić za pomocą bash w systemie Linux?
foo
(np. myfoo.jpg
), Czy pliki zawierające sekwencję bajtów foo
(które mogą obejmować pliki binarne, które akurat zawierają sekwencję bajtów)?
Chcę usunąć wszystkie pliki zawierające ciąg foo
. Jak mogę to zrobić za pomocą bash w systemie Linux?
foo
(np. myfoo.jpg
), Czy pliki zawierające sekwencję bajtów foo
(które mogą obejmować pliki binarne, które akurat zawierają sekwencję bajtów)?
Odpowiedzi:
Oto bezpieczny sposób:
grep -lrIZ foo . | xargs -0 rm -f --
-l
drukuje nazwy plików pasujących do wzorca wyszukiwania.-r
wykonuje rekurencyjne wyszukiwanie wzorca foo
w podanym katalogu .
. Jeśli to nie zadziała, spróbuj -R
.-I
(kapitał i
) powoduje pomijanie plików binarnych, takich jak pliki PDF.-Z
zapewnia, że nazwy plików są zerowane (tj. nul-), tak aby nazwa zawierająca białe znaki nie była interpretowana w niewłaściwy sposób (tzn. jako wiele nazw zamiast jednej).xargs -0
podaje nazwy plików od grep
do rm -f
, oddzielając słowa przez zero (nul) bajtów (pamiętaj -Z
opcję od grep
).--
jest często zapominany, ale bardzo ważne jest zaznaczenie końca opcji i umożliwienie usunięcia plików, których nazwy zaczynają się -
.Jeśli chcesz zobaczyć, które pliki mają zostać usunięte, po prostu usuń | xargs -0 rm -f --
część i pozostaw Z
opcję grep
.
Inny użytkownik zasugerował coś takiego, czego nie należy uruchamiać, ponieważ jest to niebezpieczne:
files=`grep foo * | cut -d: -f1`
rm -f $files # unsafe, do not run it!
Jeśli mam pliki ImportantStuff
, których nie chcę usuwać i które obsolete ImportantStuff
zawierają foo
, tracę ImportantStuff
(i nie obsolete ImportantStuff
!) Po uruchomieniu tego polecenia, ponieważ $files
rozpada się na spacje podczas interpretacji. W ten sposób umieszczanie listy nazw plików w zmiennej powłoki skalarnej jest niebezpieczne.
$ find -type f -exec grep -q "foo" {} \; -exec echo rm -- {} \;
Rekurencyjnie wyszukuje pliki zawierające foo
. Drugi -exec
jest uruchamiany tylko wtedy, gdy pierwszy exec
zakończy się pomyślnie, tzn. Jeśli grep
pasuje. Dryrun i usuń, echo
jeśli wyjście wydaje się prawidłowe.
Lub alternatywnie
$ find -type f -exec grep -q "foo" {} \; -print
i
$ find -type f -exec grep -q "foo" {} \; -delete
jak sugeruje Lekensteyn.
find -type f -exec grep -q 'foo' {} \; -delete
(cytaty {}
są zbędne, find
można także usuwać pliki). Uwaga: grep
akceptuje wyrażenie regularne. Jeśli chcesz wyszukać foo.bar
, albo uniknij tego, albo przekaż -F
opcję traktowania wzorca jako dosłownego.
-exec echo rm "{}" \;
a nie -delete
?
-delete
. Łatwiej jest zademonstrować z drugim -exec
i rozbrzmiewającym echem.
-print
(lub -ls
dla większej szczegółowości) niż -exec echo rm "{}" \'
. Nie potrzeba zewnętrznych narzędzi.
Zrobiłbym to, co mówi Adrian,
Ale dodam granice słów wokół foo, aby przypadkowo nie usunąć plików zawierających „jedzenie” (chyba że usuwa wszystko, co zawiera jedzenie).
$ find -type f -exec grep -q "\<foo\>" {} \; -delete
acutally, przekierowałem dane wyjściowe przed usunięciem, aby móc przejrzeć przed usunięciem:
$ find -type f -exec grep -q "\<foo\>" > /tmp/list_of_files_to_delete