Come eliminare più file contemporaneamente in Bash su Linux?


103

Ho questo elenco di file su un server 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

Ho cancellato i file di registro selezionati uno per uno, usando il comando rm -rfvedi sotto:

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

C'è un altro modo per eliminare i file selezionati contemporaneamente?


4
E "Dì GNU / Linux, non solo Linux", sento qualcuno tuonare dai sedili posteriori.
Boris Stitnicky

8
A proposito, perché la -rf? Sono queste cartelle? f sta per forzare, r sta per ricorsivo. Funzionerà se è solo un file, ma attenzione, usare -rf ogni volta che vuoi eliminare qualcosa è molto (molto) (molto molto) pericoloso. (e dovresti aggiungere il tag "bash" perché "linux" è troppo largo.
Depado

@ BorisStitnicky - Sono curioso di sapere perché GNUè necessario?
user66001

2
@ user66001: Per l'opinione del progetto GNU in merito: gnu.org/gnu/linux-and-gnu.html . Non prendo posizione sulla questione, almeno non qui, e non è questa la sede per discuterne.
Keith Thompson

2
@ BorisStitnicky - Non c'è bisogno di discutere, era completamente all'oscuro e quel link mi ha dato il livello di informazione che stavo cercando +1
user66001

Risposte:


159

Bash supporta tutti i tipi di caratteri jolly ed espansioni.

Il tuo caso esatto sarebbe gestito dall'espansione delle parentesi graffe , in questo modo:

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

Quanto sopra si espanderebbe in un singolo comando con tutti e tre gli argomenti, ed equivarrebbe a digitare:

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

È importante notare che questa espansione viene eseguita dalla shell, prima rmancora che venga caricata.


Non utilizzare "rm" se desideri ripristinare i file in futuro. Puoi utilizzare l'utility "rm-trash": github.com/nateshmbhat/rm-trash
Natesh bhat

75

Usa un carattere jolly ( *) per abbinare più file.

Ad esempio, il comando seguente eliminerà tutti i file i cui nomi iniziano con abc.log.2012-03-.

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

Ti consiglio di correre ls abc.log.2012-03-*per elencare i file in modo da poter vedere cosa vuoi eliminare prima di eseguire il rmcomando.

Per maggiori dettagli vedere la pagina man di Bash sull'espansione del nome file .


Molto utile, ma non chiede conferma per l'eliminazione. Si prega di essere consapevoli.
nuriselcuk

1
@nuriselcuk puoi aggiungere -i per ottenere la conferma per ogni file eliminato.
Felipe Romero

Ha funzionato a meraviglia su AWS Ec2-Instance con Amazon Linux 1 :) Grazie.
Kyle Bridenstine

41

Se si desidera eliminare tutti i file i cui nomi corrispondono a una forma particolare, un carattere jolly (glob pattern) è la soluzione più semplice. Qualche esempio:

$ 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

Le espressioni regolari sono più potenti dei caratteri jolly; puoi alimentare l'output di grepa rm -f. Ad esempio, se alcuni nomi di file iniziano con "abc.log"e altri con "ABC.log", grepconsente di eseguire una corrispondenza senza distinzione tra maiuscole e minuscole:

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

Ciò causerà problemi se uno qualsiasi dei nomi di file contiene caratteri divertenti, inclusi gli spazi. Stai attento.

Quando lo faccio, ls | grep ...eseguo prima il comando e controllo che produca l'output che desidero, specialmente se sto usando rm -f:

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

dove si !!espande al comando precedente. Oppure posso digitare freccia su o Ctrl-P e modificare la riga precedente per aggiungere il rm -fcomando.

Questo presuppone che tu stia usando la shell bash. Alcune altre shell, in particolare csh e tcsh e alcune vecchie shell derivate da sh, potrebbero non supportare la $(...)sintassi. È possibile utilizzare la sintassi di backtick equivalente:

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

Il $(...) sintassi è più facile da leggere e se sei veramente ambizioso può essere annidata.

Infine, se il sottoinsieme di file che desideri eliminare non può essere facilmente espresso con un'espressione regolare, un trucco che uso spesso è elencare i file in un file di testo temporaneo, quindi modificarlo:

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

Posso quindi modificare il listfile manualmente, lasciando solo i file che voglio rimuovere, e poi:

$ rm -f $(<list)

o

$ rm -f `cat list`

(Anche in questo caso, si presume che nessuno dei nomi di file contenga caratteri divertenti, in particolare spazi.)

Oppure, durante la modifica del listfile, posso aggiungere rm -f all'inizio di ogni riga e poi:

$ . ./list

o

$ source ./list

La modifica del file è anche un'opportunità per aggiungere virgolette dove necessario, ad esempio passando rm -f foo bara rm -f 'foo bar'.


8

Basta usare la selezione multilinea in sublime per combinare tutti i file in una singola riga e aggiungere uno spazio tra ogni nome di file e quindi aggiungere rmall'inizio dell'elenco. Ciò è particolarmente utile quando non c'è un pattern nei nomi dei file che si desidera eliminare.

[$]> 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

Questa dovrebbe essere la risposta accettata in quanto risponde esplicitamente alla domanda posta. È più amichevole per le persone che sono venute qui da Google.
ATLief

5

Un jolly funzionerebbe bene per questo, anche se per sicurezza sarebbe meglio ridurre al minimo possibile l'uso del jolly, quindi qualcosa del genere:

rm -rf abc.log.2012-*

Anche se a quanto pare, quei file sono solo singoli? L'opzione ricorsiva non dovrebbe essere necessaria se nessuno di questi elementi è directory, quindi è meglio non usarla, solo per sicurezza.


2

Non sono un guru di Linux, ma credo che tu voglia reindirizzare il tuo elenco di file di output a xargs rm -rf. Ho usato qualcosa di simile in passato con buoni risultati. Prima prova su una directory di esempio!

EDIT - Potrei aver capito male, sulla base delle altre risposte che appaiono. Se puoi usare i caratteri jolly, bene. Ho pensato che il tuo elenco originale che hai visualizzato fosse generato da un programma per darti la tua "selezione", quindi ho pensato che il collegamento xargssarebbe stato la strada da percorrere.


-1

se vuoi eliminare tutti i file che appartengono a una directory contemporaneamente. Ad esempio: il nome della directory è "log" e la directory "log" include file abc.log.2012-03-14, abc.log.2012-03-15, ... ecc. Devi essere sopra la directory dei log e:

rm -rf /log/*
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.