Pipingowanie find -name na xargs powoduje, że nazwy plików nie są przekazywane do polecenia

26

Zwykle aby usunąć pliki ze spacjami w nazwie pliku, należy uruchomić:

$ rm "file name"

ale jeśli chcę usunąć wiele plików, np .:

$ find . -name "*.txt" | xargs rm

Nie spowoduje to usunięcia plików ze spacjami.

Ashley
źródło
Całkowicie zgadnij tutaj: czy find -name "*\ *.txt" | xargs rmdziała na dwa pliki słów?
Wędrowiec

Odpowiedzi:

49

Możesz powiedzieć findi xargsużywać zarówno terminatorów zerowych

find . -name "*.txt" -print0 | xargs -0 rm

lub (prościej) użyj wbudowanej -deleteakcjifind

find . -name "*.txt" -delete

lub (dzięki @kos)

find . -name "*.txt" -exec rm {} +

który z nich powinien przestrzegać ARG_MAXlimitu systemu bez potrzeby xargs.

steeldriver
źródło
1
Nie mogę głosować za tym dwa razy ciężko :), ponieważ wspomniałeś ARG_MAX, że wspomnę również, że find . -name "*.txt" -exec rm {} \;byłby to „bezpieczny strzał”
Kos
3
Tak mówi mistrz: zawsze pamiętaj xargs -0.
Joshua
1
Bardzo ważny punkt: -print0musi być ostatnią opcją (lub przynajmniej później -name "*.txt"), w przeciwnym razie spowoduje to uderzenie plików nie ograniczonych już do*.txt ...
Kev
1

Nawiasem mówiąc, jeśli użyłeś czegoś innego niż find, możesz użyć tr, aby zastąpić znaki nowej linii bajtami zerowymi.

Na przykład. poniższy jeden linijka usuwa 10 ostatnio zmodyfikowanych plików w katalogu, nawet jeśli mają w nazwach spacje.

ls -tp | grep -v / | head -n 10 | tr "\n" "\0" | xargs -0 rm

Ibrahim
źródło
Tak, to działa.
Peter Mortensen
0

Polecenie xargs domyślnie używa tabulatorów, spacji i nowych linii jako ograniczników. Możesz powiedzieć, aby używał tylko znaków nowej linii ('\ n') z opcją -d:

find . -name "*.txt" | xargs -d '\n' rm

Odpowiedź źródła na SO .

joseph_morris
źródło
Ta odpowiedź wymienia -0zamiast -d(for xargs) dla systemów BSD. Czego używa Ubuntu? Zastosowano tutaj zaakceptowaną odpowiedź -0. Co jest poprawne?
Peter Mortensen