Jak usunąć wiele plików jednocześnie w Bash w systemie Linux?

103

Mam tę listę plików na serwerze Linux:

abc.log.2012-03-14
abc.log.2012-03-27
abc.log.2012-03-28
abc.log.2012-03-29
abc.log.2012-03-30
abc.log.2012-04-02
abc.log.2012-04-04
abc.log.2012-04-05
abc.log.2012-04-09
abc.log.2012-04-10

Usunąłem wybrane pliki dziennika jeden po drugim, używając polecenia rm -rfpatrz poniżej:

rm -rf abc.log.2012-03-14
rm -rf abc.log.2012-03-27
rm -rf abc.log.2012-03-28

Czy jest inny sposób, abym mógł od razu usunąć wybrane pliki?

user1253847
źródło
4
I „Powiedz GNU / Linux, nie tylko Linux”, słyszę, jak ktoś grzmi z tylnych siedzeń.
Boris Stitnicky
8
Swoją drogą, dlaczego -rf? Czy to te foldery? f to wymuszenie, r rekurencyjne. Będzie działać, jeśli jest to tylko plik, ale ostrzegamy, że użycie -rf za każdym razem, gdy chcesz usunąć coś, jest bardzo (bardzo) (bardzo) niebezpieczne. (i powinieneś dodać tag „bash”, ponieważ „linux” jest za szeroki.
Depado
@BorisStitnicky - jestem ciekaw, dlaczego GNUjest potrzebny?
user66001
2
@ user66001: Aby zapoznać się z opinią projektu GNU w tej sprawie: gnu.org/gnu/linux-and-gnu.html . Nie zajmuję stanowiska w tej sprawie, przynajmniej nie tutaj, i nie jest to miejsce na debatę.
Keith Thompson
2
@BorisStitnicky - Nie trzeba debatować, był kompletnie nieświadomy, a ten link dał mi poziom informacji, którego szukałem +1
user66001

Odpowiedzi:

160

Bash obsługuje wszystkie rodzaje symboli wieloznacznych i rozszerzeń.

Twój dokładny przypadek byłby obsługiwany przez rozwinięcie nawiasów , na przykład:

$ rm -rf abc.log.2012-03-{14,27,28}

Powyższe rozwinęłoby się do jednego polecenia ze wszystkimi trzema argumentami i byłoby równoważne wpisaniu:

$ rm -rf abc.log.2012-03-14 abc.log.2012-03-27 abc.log.2012-03-28

Należy zauważyć, że ta ekspansja jest wykonywana przez powłokę, zanim rmjeszcze zostanie załadowana.

rozwijać
źródło
Nie używaj „rm”, jeśli chcesz przywrócić pliki w przyszłości. Możesz użyć narzędzia „rm-trash”: github.com/nateshmbhat/rm-trash
Natesh bhat
76

Użyj symbolu wieloznacznego ( *), aby dopasować wiele plików.

Na przykład poniższe polecenie usunie wszystkie pliki z nazwami zaczynającymi się od abc.log.2012-03-.

rm -f abc.log.2012-03-*

Zalecam uruchomienie, ls abc.log.2012-03-*aby wyświetlić listę plików, aby zobaczyć, co zamierzasz usunąć przed uruchomieniem rmpolecenia.

Aby uzyskać więcej informacji, zobacz stronę podręcznika Bash dotyczącą rozszerzania nazw plików .

dogbane
źródło
Bardzo przydatne, ale nie prosi o potwierdzenie usunięcia. Proszę bądź świadom.
nuriselcuk
1
@nuriselcuk możesz dodać -i, aby uzyskać potwierdzenie każdego usuwanego pliku.
Felipe Romero
Działał jak urok na AWS Ec2-Instance z systemem Amazon Linux 1 :) Dziękuję.
Kyle Bridenstine
41

Jeśli chcesz usunąć wszystkie pliki, których nazwy pasują do określonego formularza, najprostszym rozwiązaniem jest użycie symbolu wieloznacznego (wzorzec glob). Kilka przykładów:

$ rm -f abc.log.*             # Remove them all
$ rm -f abc.log.2012*         # Remove all logs from 2012
$ rm -f abc.log.2012-0[123]*  # Remove all files from the first quarter of 2012

Wyrażenia regularne mają większe możliwości niż symbole wieloznaczne; możesz podać wyjście grepdo rm -f. Na przykład, jeśli niektóre nazwy plików zaczynają się od, "abc.log"a inne od "ABC.log", grepumożliwia dopasowanie bez rozróżniania wielkości liter:

$ rm -f $(ls | grep -i '^abc\.log\.')

Spowoduje to problemy, jeśli którakolwiek z nazw plików zawiera zabawne znaki, w tym spacje. Bądź ostrożny.

Kiedy to robię, ls | grep ...najpierw uruchamiam polecenie i sprawdzam, czy generuje dane wyjściowe, których potrzebuję - zwłaszcza jeśli używam rm -f:

$ ls | grep -i '^abc\.log\.'
(check that the list is correct)
$ rm -f $(!!)

gdzie !!rozwija się do poprzedniego polecenia. Lub mogę wpisać strzałkę w górę lub Ctrl-P i edytować poprzednią linię, aby dodaćrm -f polecenie.

Zakłada się, że używasz powłoki bash. Niektóre inne powłoki, szczególnie csh i tcsh oraz niektóre starsze powłoki wyprowadzone z sh, mogą nie obsługiwać $(...)składni. Możesz użyć równoważnej składni backtick:

$ rm -f `ls | grep -i '^abc\.log\.'`

Plik $(...)Składnia jest bardziej czytelna, a jeśli jesteś naprawdę ambitny może być zagnieżdżona.

Wreszcie, jeśli podzbioru plików, które chcesz usunąć, nie można łatwo wyrazić za pomocą wyrażenia regularnego, sztuczka, której często używam, polega na umieszczeniu plików w tymczasowym pliku tekstowym, a następnie edytowaniu go:

$ ls > list
$ vi list   # Use your favorite text editor

Mogę wtedy listręcznie edytować plik, pozostawiając tylko te pliki, które chcę usunąć, a następnie:

$ rm -f $(<list)

lub

$ rm -f `cat list`

(Ponownie zakłada się, że żadna z nazw plików nie zawiera zabawnych znaków, zwłaszcza spacji).

Lub podczas edycji listpliku mogę dodać rm -f na początku każdego wiersza, a następnie:

$ . ./list

lub

$ source ./list

Edycja pliku to także możliwość dodania cytatów w razie potrzeby, na przykład zmiany rm -f foo barna rm -f 'foo bar'.

Keith Thompson
źródło
8

Po prostu użyj wysublimowanego wyboru wielowierszowego, aby połączyć wszystkie pliki w jedną linię i dodać spację między każdą nazwą pliku, a następnie dodać rmna początku listy. Jest to szczególnie przydatne, gdy w nazwach plików, które chcesz usunąć, nie ma wzorca.

[$]> rm abc.log.2012-03-14 abc.log.2012-03-27 abc.log.2012-03-28 abc.log.2012-03-29 abc.log.2012-03-30 abc.log.2012-04-02 abc.log.2012-04-04 abc.log.2012-04-05 abc.log.2012-04-09 abc.log.2012-04-10
Andy
źródło
To powinna być akceptowana odpowiedź, ponieważ jednoznacznie odpowiada na postawione pytanie. Jest bardziej przyjazny dla ludzi, którzy przyszli tu z Google.
ATLief
5

Dzika karta dobrze by się do tego nadawała, chociaż dla bezpieczeństwa najlepiej byłoby, aby jej użycie było jak najmniejsze, więc coś w tym stylu:

rm -rf abc.log.2012-*

Chociaż wygląda na to, że to tylko pojedyncze pliki? Opcja rekurencyjna nie powinna być konieczna, jeśli żaden z tych elementów nie jest katalogiem, więc najlepiej jej nie używać, tylko ze względów bezpieczeństwa.

lacrosse1991
źródło
2

Nie jestem guru Linuksa, ale wierzę, że chcesz przesłać swoją listę plików wyjściowych xargs rm -rf. Użyłem czegoś takiego w przeszłości z dobrymi wynikami. Najpierw przetestuj na przykładowym katalogu!

EDYCJA - mogłem źle zrozumieć, na podstawie innych pojawiających się odpowiedzi. Jeśli możesz używać symboli wieloznacznych, świetnie. Założyłem, że Twoja oryginalna lista, którą wyświetlasz, została wygenerowana przez program, aby dać Ci wybór, więc pomyślałem, że najlepszym xargsrozwiązaniem będzie przekierowanie do.

Dave
źródło
-1

jeśli chcesz jednocześnie usunąć wszystkie pliki należące do katalogu. Na przykład: nazwa katalogu to „log”, a katalog „log” zawiera pliki abc.log.2012-03-14, abc.log.2012-03-15, ... itd. Musisz znajdować się nad katalogiem dziennika i:

rm -rf /log/*
Alican
źródło