Jak mogę potokować ls do grep i usunąć pliki filtrowane przez grep?

33

Chciałem usunąć część pakietu z mojego pliku domowego, ale nazwa pliku była zbyt długa ( google-chrome-stable_current_i386.deb). Dlatego postanowiłem użyć polecenia ls|grep chrome|rmdo potokowania plików, aby grep odfiltrował plik chrome, a następnie go usunął. Nie działało, więc chciałbym zobaczyć, jak to zrobić.

SpecialBomb
źródło
22
rm -i *chrome*.deb
Lambert,
28
Ogólnie rzecz biorąc, nie lubię, gdy ludzie publikują odpowiedzi „nie rób tego”, ale jest to jeden z najlepszych przykładów problemu XY , jaki kiedykolwiek widziałem. Twoje prawdziwe pytanie brzmi: „jak szybko usunąć plik z długą nazwą pliku, bez wpisywania całego tekstu”, i istnieje wiele dobrych sposobów, które nie wymagają grepowania danych wyjściowychls
Michael Mrozek
5
Po prostu użyj find- find . -name "*chrome*" -delete.
Boris the Spider
3
Moje dwa centy jako użytkownik StackExchange: w przyszłości zadaj pytanie w bardziej ogólny sposób, podając szczegóły na temat tego, czego próbowałeś. „Jak usunąć pliki w folderze z określonym ciągiem w nazwie pliku?” mógłby być lepszym sposobem na wyrażenie tego. Następnie można po prostu dodać, na marginesie, że próbowałeś rurociąg lsprzez grepsię rm, ale nie mógł dostać się do pracy. W ten sposób otrzymasz jedną lub dwie dobre odpowiedzi na temat „poprawnego” lub „najłatwiejszego” sposobu wykonania zadania, zamiast zmuszać kogoś do udzielenia dobrej odpowiedzi na temat nieefektywnego rozwiązania.
Adrian,

Odpowiedzi:

56

To prawie sprawiło, że się skrzywiłem.

  1. Możesz przestać celować strzelbą w nogę. W zasadzie każdy rodzaj parsowanie lsbędzie bardziej skomplikowane i podatne na błędy niż ustalonych metod, jak find [...] -execi globs .
  2. O ile ktoś nie zainstalował dla ciebie dystrybucji trolli, twoja powłoka jest Tabukończona. Po prostu wpisz rm googlei naciśnij Tab. Jeśli nie zakończy się natychmiast, naciśnij Tabponownie, aby wyświetlić listę pasujących plików. Wpisz więcej znaków w nazwie pliku, aby zawęzić go do końca, a następnie uruchom polecenie.
  3. Rury ! = Parametry . Standardowe wejście to binarny strumień danych, który można asynchronicznie podać do polecenia. Parametry to ciągi rozdzielone spacjami, które są przekazywane raz i tylko raz do polecenia podczas jego uruchamiania. Są to bardzo rzadko wymienne.
10b0
źródło
1
Przepraszam, jeśli to wydawało się pytaniem n00b. Wiedziałem, że ogólnie można używać, ponieważ podany pakiet był jedynym pakietem z „chrome”. Dlatego użycie grep odfiltrowałoby tylko jeden plik. Jestem całkiem nowy w Linuksie i już zrobiłem wiele skryptów bash, ale nie wiem jeszcze wszystkiego: P. Ostry, stary.
SpecialBomb,
5
Nie chciałem być szorstki, ale powłoka jest trudnym i bezlitosnym środowiskiem, ukrytym za przyjazną dla użytkownika powierzchnią. Bezpieczne robienie rzeczy jest wystarczająco trudne, nie wspominając o tym bezpiecznie, a nawet poprawnie .
l0b0,
2
@SpecialBomb To jedyna poprawna odpowiedź. Wyjaśnienie, jak prawidłowo celować strzelbę, aby dokładnie odciąć stopę, podobnie jak inne odpowiedzi, z pewnością nie jest dobrym rozwiązaniem. Uważaj szczególnie na ślepe wykonywanie rm- prawdopodobnie jest to jeden z bardziej powszechnych sposobów smażenia dystrybucji.
Boris the Spider
@ BoristheSpider Heh, zdecydowanie już usmażyłem Ubuntu dwukrotnie instalując sterowniki karty graficznej AMD. Ale już zadałem o to pytanie. AMD było okropne, więc zapytałem, czy są jakieś typowe poprawki lub lepsze metody grania w Linuksie na karcie AMD.
SpecialBomb
34

Możesz także użyć polecenia find ze znakiem wieloznacznym:

find . -maxdepth 1 -name '*chrome*' -delete

Zauważ, że argument „-maxdepth” zapewnia, że ​​find działa tylko w bieżącym katalogu i nie powraca do podkatalogów.

cedzak
źródło
1
Sugestie dotyczące ulepszeń: (a) użyj -inamedla nazw plików bez rozróżniania wielkości liter (b) potok do xargsużywania -print0flag dla findi -0flag dla xargs. Użycie xargspozwala na wykonywanie czynności takich jak „interaktywne” (potwierdzanie usunięcia foo?) Usuwanie .
Christopher Schultz,
3
Nie musisz przesyłać strumieniowo do xargs, jeśli użyjesz opcji -exec:find . -name '*chrome*' -exec rm -i {} +
Johnny
4
Czy to również nie usunie rekurencyjnie do podkatalogów? Konieczne może być podanie wartości maxdepth1.
Tyzoid
32

Miałeś dobry pomysł, po prostu przegapiłeś kilka szczegółów. Ponieważ masz do czynienia z listą zbliżającą się do STDIN i rmoczekuje parametrów, musisz użyć xargs.

A zatem:

ls | grep chrome | xargs rm

Powinien dać ci to, czego chcesz.

Pamiętaj, że jeśli chcesz usunąć wszystko inne niż chromeplik, możesz po prostu dodać -vdo grepwyciągu.

Pamiętaj, że według innych odpowiedzi na to pytanie jest to prawdopodobnie zły sposób na osiągnięcie tego, co chcesz osiągnąć.

Jan
źródło
Dzięki -v, czy to nie usunie wszystkiego oprócz pasujących plików chrome? Nie sądzę, że tego chce OP…
akivajgordon,
Patrząc ponownie, masz rację. OP chce „odfiltrować plik chrome”, ale następnie chce go usunąć.
John,
To wydaje się niepotrzebnie skomplikowane, w porównaniu do prostego „rm -i chrome
Chander
5
Przyjęta odpowiedź działa, ale patrz odpowiedź poniżej, która wyjaśnia, dlaczego jest to zły pomysł. (Publikowanie tego komentarza tutaj tylko ze względu na tych, którzy zatrzymują się, gdy tylko zobaczą „zaakceptowany” znacznik wyboru.)
Jim Davis,
1
Ta zaakceptowana odpowiedź „działa” tylko wtedy, gdy na lswyjściu nie ma „dziwnych” nazw plików . Nazwy plików ze spacjami to zniszczą. Jest to również niebezpieczne, jeśli ktoś może skonstruować nazwę pliku ze specjalnym sosem w katalogu, w którym to uruchomisz. Jak już zauważyła więcej niż jedna osoba, nie analizuj wyniku działania ls !
Stephen P,
11

Nigdy nie analizuj danych wyjściowych ls.
Sugeruję, aby unikać analizowania danych wyjściowych ls [ 1 ] , a nawet więcej, jeśli są one połączone z delpoleceniem. Jest to z wielu powodów głównie związane z nieoczekiwanymi i nietypowymi znakami dozwolonymi w nazwie pliku.

Nawet jeśli powinieneś spodziewać się, że nazwy plików należących do pakietów Linuksa będą „zachowywać się dobrze” , problem ten może się pojawić, jeśli w tym samym katalogu znajdują się inne pliki, ale nie wiedziałeś o tym ani nie zauważyłeś.

Lepiej używać find, rozwijania tabulatorów (zacznij pisać nazwę i naciśnij Tab), rozwijania nazw plików [ 2 ] jako *MyKey*...


Szybkie rozwiązanie
Ponieważ chcesz wybrać wszystkie pakiety (które kończą się .deb) za pomocą „google” w środku, możesz zbudować swoje zapytanie przy użyciu symbolu wieloznacznego * *google*.debi zrobić proste

rm -i *google*.deb 

która wybierze każdą nazwę pliku z „google” pośrodku, która zakończy się jako .debobecna w bieżącym katalogu. Opcja -i(interaktywna) poprosi o potwierdzenie, co jest dobrym nawykiem podczas usuwania plików z rozszerzaniem parametrów.


Rozwiązanie zbliżone do filozofii twojej próby
Jeśli twoim celem jest budowanie linii poleceń kawałek po kawałku, więc zrobiłeś to lspo ls | grep googlei tylko po sprawdzeniu wyjścia , możesz wykonać go w podpowłoce za $(...)pomocą

rm -i $(ls | grep google)

Szybszym i bardziej niebezpiecznym sposobem [ 3 ] jest użycie!!

ls | grep google
rm -i $(!!)

które wykona ostatnie polecenie zakończone w twojej historii . Można chronić się z faktu, że nie masz wizualną kontrolę linii, które masz zamiar wykonać, jeśli włączono wcześniej opcji powłoki histverifyz shopt -s histverify.

Hastur
źródło
5
touch 0 1 2 3 4 5 6 7 8 9
find . -name \[0-9] -ok rm {} \;

< rm ... ./0 > ? y
< rm ... ./9 > ? y
< rm ... ./8 > ? y
< rm ... ./7 > ? y
< rm ... ./6 > ? y
< rm ... ./5 > ? y
< rm ... ./4 > ? y
< rm ... ./3 > ? y
< rm ... ./2 > ? y
< rm ... ./1 > ? y
^C

... -name '*c*.deb'zamiast tego użyj lub innego wzoru, który Ci odpowiada.

mikeserv
źródło
2

rmnie akceptuje danych wejściowych od stdin. Musisz zrobić coś takiegols google-chrome* | xargs rm

David King
źródło