Como excluir vários arquivos de uma vez no Bash no Linux?

103

Tenho esta lista de arquivos em um servidor 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

Estou excluindo arquivos de log selecionados um por um, usando o comando rm -rfabaixo:

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

Existe outra maneira de excluir os arquivos selecionados de uma vez?

user1253847
fonte
4
E "Diga GNU / Linux, não apenas Linux", eu ouço alguém trovejando nos assentos de trás.
Boris Stitnicky
8
A propósito, por que o -rf? Essas são pastas? f é forçar, r é recursivo. Funcionará se for apenas um arquivo, mas esteja avisado, usar -rf cada vez que você quiser deletar algo é muito (muito) (muito) perigoso. (e você deve adicionar a tag "bash" porque "linux" é muito largo.
Depado
@BorisStitnicky - Estou curioso para saber por que GNUé necessário?
user66001
2
@ user66001: Para a opinião do projeto GNU sobre o assunto: gnu.org/gnu/linux-and-gnu.html . Não tomo posição sobre o assunto, pelo menos não aqui, e não é este o lugar para o debater.
Keith Thompson
2
@BorisStitnicky - Não há necessidade de debater, estava completamente sem noção, e aquele link me deu o nível de informação que eu estava procurando +1
user66001

Respostas:

159

O Bash suporta todos os tipos de curingas e expansões.

Seu caso exato seria tratado pela expansão da chave , assim:

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

O código acima se expandiria para um único comando com todos os três argumentos e seria equivalente a digitar:

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

É importante notar que essa expansão é feita pelo shell, antes rmmesmo de ser carregada.

desanuviar
fonte
Não use "rm" se desejar restaurar os arquivos no futuro. Você pode usar o utilitário "rm-trash": github.com/nateshmbhat/rm-trash
Natesh bhat
75

Use um curinga ( *) para corresponder a vários arquivos.

Por exemplo, o comando abaixo excluirá todos os arquivos com nomes que começam com abc.log.2012-03- .

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

Eu recomendo correr ls abc.log.2012-03-* para listar os arquivos para que você possa ver o que vai deletar antes de executar o rmcomando.

Para obter mais detalhes, consulte a página de manual do Bash sobre expansão de nome de arquivo .

dogbane
fonte
Muito útil, mas não está pedindo confirmação para excluir. Por favor, esteja ciente.
nuriselcuk
1
@nuriselcuk você pode adicionar -i para obter a confirmação de cada arquivo sendo excluído.
Felipe Romero
Funcionou como um encanto na AWS Ec2-Instance rodando Amazon Linux 1 :) Obrigado.
Kyle Bridenstine
41

Se você deseja excluir todos os arquivos cujos nomes correspondem a um determinado formulário, um curinga (padrão glob) é a solução mais direta. Alguns exemplos:

$ 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

As expressões regulares são mais poderosas do que os curingas; você pode alimentar a saída de greppara rm -f. Por exemplo, se alguns dos nomes de arquivo começam com "abc.log"e alguns com "ABC.log", greppermite fazer uma correspondência sem distinção entre maiúsculas e minúsculas:

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

Isso causará problemas se algum dos nomes de arquivo contiver caracteres engraçados, incluindo espaços. Seja cuidadoso.

Quando faço isso, executo o ls | grep ...comando primeiro e verifico se ele produz a saída que desejo - especialmente se estiver usando rm -f:

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

onde se !!expande para o comando anterior. Ou posso digitar seta para cima ou Ctrl-P e editar a linha anterior para adicionar o rm -fcomando.

Isso pressupõe que você está usando o shell bash. Alguns outros shells, particularmente csh e tcsh e alguns shells derivados de sh mais antigos, podem não suportar a $(...)sintaxe. Você pode usar a sintaxe de crase equivalente:

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

A $(...)sintaxe é mais fácil de ler e, se você for realmente ambicioso, pode ser aninhada.

Finalmente, se o subconjunto de arquivos que você deseja excluir não pode ser facilmente expresso com uma expressão regular, um truque que costumo usar é listar os arquivos em um arquivo de texto temporário e, em seguida, editá-lo:

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

Posso então editar o listarquivo manualmente, deixando apenas os arquivos que desejo remover e, em seguida:

$ rm -f $(<list)

ou

$ rm -f `cat list`

(Novamente, isso pressupõe que nenhum dos nomes de arquivo contém caracteres engraçados, especialmente espaços.)

Ou, ao editar o listarquivo, posso adicionar rm -f no início de cada linha e então:

$ . ./list

ou

$ source ./list

Editar o arquivo também é uma oportunidade para adicionar cotações quando necessário, por exemplo, mudar rm -f foo barpara rm -f 'foo bar'.

Keith Thompson
fonte
8

Basta usar a seleção multilinha no sublime para combinar todos os arquivos em uma única linha e adicionar um espaço entre cada nome de arquivo e adicionar rmno início da lista. Isso é útil principalmente quando não há um padrão nos nomes de arquivo que você deseja excluir.

[$]> 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
fonte
Esta deve ser a resposta aceita, pois responde explicitamente à questão colocada. É mais amigável para as pessoas que vieram do Google.
ATLief
5

Um curinga funcionaria bem para isso, embora, para ser seguro, seria melhor fazer o uso do curinga o mínimo possível, então algo mais ou menos assim:

rm -rf abc.log.2012-*

Embora, ao que parece, esses sejam apenas arquivos individuais? A opção recursiva não deve ser necessária se nenhum desses itens forem diretórios, então é melhor não usá-la, apenas por segurança.

lacrosse1991
fonte
2

Não sou um guru do Linux, mas acredito que você queira canalizar sua lista de arquivos de saída para xargs rm -rf. Eu usei algo assim no passado com bons resultados. Teste primeiro em um diretório de amostra!

EDITAR - Posso ter entendido mal, com base nas outras respostas que estão aparecendo. Se você pode usar curingas, ótimo. Presumi que a lista original que você exibiu foi gerada por um programa para dar a você sua "seleção", então pensei que piping para xargsseria o caminho a percorrer.

Dave
fonte
-1

se você deseja excluir todos os arquivos que pertencem a um diretório de uma vez. Por exemplo: o nome do seu diretório é "log" e o diretório "log" inclui os arquivos abc.log.2012-03-14, abc.log.2012-03-15, ... etc. Você deve estar acima do diretório de log e:

rm -rf /log/*
Alican
fonte