Usuwanie plików ze spacjami w ich nazwach

10

Próbuję usunąć wszystkie pliki ze spacjami w nazwach. Korzystam z następującego polecenia. Ale to daje mi błąd

Komenda : ls | egrep '. ' | xargs rm

Tutaj, jeśli używam tylko ls | egrep '. 'polecenia, daje mi całą nazwę pliku ze spacjami w nazwach plików. Ale gdy próbuję przekazać dane wyjściowe do rm, wszystkie spacje (początkowe lub końcowe) zostają usunięte. Więc moje polecenie nie wykonuje się poprawnie.

Wszelkie wskazówki na temat usuwania pliku mającego co najmniej jedno miejsce w nazwie?

Anuj
źródło

Odpowiedzi:

29

Możesz użyć standardowego globowania w rmpoleceniu:

rm -- *\ *

Spowoduje to usunięcie dowolnego pliku, którego nazwa zawiera spację; spacja jest usuwana, więc powłoka nie interpretuje go jako separatora. Dodanie --pozwoli uniknąć problemów z nazwami plików rozpoczynającymi się od myślników (nie będą one interpretowane jako argumenty przez rm).

Jeśli chcesz potwierdzić każdy plik przed jego usunięciem, dodaj -iopcję:

rm -i -- *\ *
Stephen Kitt
źródło
4
Na pewno będziesz chciał to zrobić echo, aby uniknąć literówek. Dodaj echoz przodu, a wydrukuje wszystkie pliki, które zamierza usunąć.
Riking
1
Anuj, powodem tego jest najwięcej entuzjazmu, ponieważ chociaż findjest potężny, czasami nie musisz zabijać kurczaka za pomocą karabinu maszynowego. Administratorzy systemu UNIX zazwyczaj nie używają find(na przykład) „usuwania wszystkich plików zaczynających się na literę A” ... po prostu rm A*. Podobnie, aby usunąć pliki zawierające spacje, rm może wykonać to zadanie. Innymi słowy, nie daj się zwieść, ponieważ przestrzeń jest niewidoczna i jest specjalnie traktowana przez powłokę. Po prostu ucieknij, jak zrobił to Stephen Kitt, i możesz myśleć o tym jak o każdej innej postaci.
Mike S
14

Unikałbym analizowania lswyników

Dlaczego nie :

find . -type f -name '* *' -delete

Nie ma problemu z rm:-).

Chociaż jest to rekurencyjne i spowoduje usunięcie wszystkich plików ze spacją w bieżącym katalogu i zagnieżdżonych katalogach, jak wspomniano w komentarzach.

przesilenie dnia z nocą
źródło
4
(1) możesz użyć -name '* *'zamiast wyrażenia regularnego; oraz (2) możesz użyć, -print0 | xargs -0 rm -iaby rozwiązać problem @ StephenKitt.
Kevin
1
Nie ma potrzeby xargs. Wystarczy użyć-exec rm -i '{}' +
R .. GitHub ZATRZYMAJ POMOC ICE
1
@Mhmd Ma więcej pułapek niż 8-bitowa konsola do gier. mywiki.wooledge.org/ParsingLs
Daenyth
1
Jeśli chcesz uniknąć podkatalogów, użyj find . -maxdepth 1 -name '* *' -delete.
Mikkel
1
@BenjaminW. naprawiony ?
solsTiCe
6

Spójrz na to Załóżmy nazwę „dziwny plik”

Rozwiązanie pierwsze

rm strange\ file

rozwiązanie drugie

rm "strange file"

rozwiązanie trzecie

ls -i "strange file"

wtedy zobaczysz i-węzeł

find . -inum "numberoofinode" -exec rm {} \;

W przypadku bardzo dziwnych nazw plików takich jak

!-filename or --filename

posługiwać się

rm ./'!-filename'
Elbarna
źródło
4

Od man xargs

xargs odczytuje elementy ze standardowego wejścia, oddzielone spacjami (które można zabezpieczyć podwójnymi lub pojedynczymi cudzysłowami lub odwrotnym ukośnikiem) lub znakami nowej linii, i wykonuje polecenie (domyślnie jest to / bin / echo) jeden lub więcej razy z następującymi argumentami początkowymi według elementów odczytanych ze standardowego wejścia. Puste linie na standardowym wejściu są ignorowane.

Możemy (głównie) naprawić początkowe polecenie, zmieniając separator xargs na nowy wiersz:

ls | egrep '. ' | xargs -d '\n' rm (nie rób tego ... czytaj dalej)

Ale co jeśli nazwa pliku zawiera nowy wiersz?

touch "filename with blanks and newline"

Ponieważ nazwy plików w systemie Unix mogą zawierać spacje i znaki nowej linii , to domyślne zachowanie jest często problematyczne; nazwy plików zawierające spacje i / lub znaki nowej linii są niepoprawnie przetwarzane przez xargs. W takich sytuacjach lepiej jest użyć opcji -0 , która zapobiega takim problemom.

ls jest tak naprawdę narzędziem do bezpośredniego spożycia przez człowieka , zamiast tego musimy użyć findpolecenia, które może oddzielić nazwy plików znakiem null ( -print0). Musimy także powiedzieć grepowi, aby używał znaków null do oddzielenia input ( -z) i output ( -Z). Na koniec mówimy xargsowi, aby używał również znaków null ( -0)

find . -type f -print0 | egrep '. ' -z -Z | xargs -0 rm

anjsimmo
źródło
1

Możesz użyć:

find . -name '* *' -delete
Max ZHUANG
źródło
rm - * \ * wydaje się lepszy
Max ZHUANG
Również to zostało uwzględnione w komentarzu Kevina do odpowiedzi solsTiCe.
G-Man mówi „Reinstate Monica”
-1

Aby to zrobić, będziesz potrzebował -Zopcji grep i -0opcji xargs. Ale nie zrobiłbym tego w ten sposób ( lsnie jest to odpowiednie narzędzie do pracy, istnieje wiele problemów z odczytaniem przez komputer danych wyjściowych).

Zobacz inne odpowiedzi na lepszy sposób.


Również

ls | …jest równoważne z ls -d *iecho * | …

Wszystkie mają problemy. Dlatego nie używaj w lsten sposób, użyj rozwiązania z innej odpowiedzi.

ctrl-alt-delor
źródło
Również ls *gdy potoki wypisują nazwy plików rozdzielane nową linią. echo(przynajmniej niektóre echoimplementacje) rozwija sekwencje odwrotnego ukośnika. grep -Zsłuży do pisania nazw plików rozdzielanych przez NUL podczas używania -l, nie pomoże to tutaj. Jeśli miałeś na myśli -z, to też nie pomoże, ponieważ większość lsimplementacji nie ma opcji wyświetlania nazw plików rozdzielanych przez NUL. Można jednak zrobić coś takiego printf '%s\0' * | grep -z ' ' | xargs -r0 rm -f.
Stéphane Chazelas,
1
@Kusalananda Myślę, że to naprawiłem.
ctrl-alt-delor