No Linux, como posso encontrar todos os arquivos que contêm uma string e excluí-los?


17

Eu quero excluir todos os arquivos que contêm a string foo. Como posso fazer isso usando o bash no Linux?


essa string é o nome do arquivo?
rɑːdʒɑ

3
Por favor, esclareça: você deseja excluir arquivos cujo nome contenha foo(por exemplo myfoo.jpg) ou arquivos que contenham a sequência de bytes foo(que podem incluir arquivos binários que por acaso contenham essa sequência de bytes)?
Hammar

Respostas:


33

Aqui está uma maneira segura:

grep -lrIZ foo . | xargs -0 rm -f --
  • -l imprime nomes de arquivos que correspondem ao padrão de pesquisa.
  • -rrealiza uma pesquisa recursiva para o padrão foono diretório especificado .. Se isso não funcionar, tente -R.
  • -I(capital i) faz com que arquivos binários como PDFs sejam ignorados.
  • -Z garante que os nomes dos arquivos sejam zerados (ou seja, nul-), para que um nome contendo espaço em branco não seja interpretado da maneira errada (ou seja, como vários nomes em vez de um).
  • xargs -0alimenta os nomes dos arquivos de greppara rm -f, separando as palavras por zero (nul) bytes (lembre-se da -Zopção de grep).
  • --é frequentemente esquecido, mas é muito importante marcar o final das opções e permitir a remoção de arquivos cujos nomes começam com -.

Se você deseja ver quais arquivos estão prestes a serem excluídos, remova a | xargs -0 rm -f --peça e deixe a Zopção para grep.

Outro usuário sugeriu algo como o seguinte, que você não deve executar porque não é seguro:

files=`grep foo * | cut -d: -f1`
rm -f $files         # unsafe, do not run it!

Se eu tiver arquivos ImportantStuffque não desejo excluir e obsolete ImportantStuffconter foo, perco ImportantStuff(e não obsolete ImportantStuff !) Quando executo esse comando, porque $filesé desmembrado em espaços quando é interpretado. É perigoso colocar uma lista de nomes de arquivos em uma variável de shell escalar dessa maneira.


17
$ find -type f -exec grep -q "foo" {} \; -exec echo rm -- {} \;

Isso recursivamente procura por arquivos que contenham foo. O segundo -execsó é executado se o primeiro execsair com êxito, ou seja, se grepcorresponder. Dryrun e remova o echose a saída parece correta.

Ou alternativamente

$ find -type f -exec grep -q "foo" {} \; -print

e

$ find -type f -exec grep -q "foo" {} \; -delete

como sugerido por Lekensteyn.


4
... que pode ser reduzido para: find -type f -exec grep -q 'foo' {} \; -delete(as aspas {}são redundantes, findtambém é possível excluir arquivos.). Observe que grepaceita uma expressão regular. Se você deseja procurar foo.bar, escape ou passe a -Fopção de tratar o padrão como literal.
Lekensteyn

alguma razão para usar -exec echo rm "{}" \;e não -delete?
vartec

11
@artec Não, eu usaria -delete. É mais fácil demonstrar com o segundo -exece eco no lugar.
Adrian Frühwirth

11
É mais fácil digitar -print(ou -lspara mais verbosidade) que -exec echo rm "{}" \'. Não há necessidade de utilitários externos.
Lekensteyn

11
se você usar rm {}, use rm - {}, para que nenhum caractere especial no nome do arquivo seja interpolado. Por exemplo, toque em '-rf /' em qualquer diretório em que você tenha permissões de gravação ...
atk

1

Eu faria o que Adrian diz,

Mas eu adicionaria limites de palavras ao redor para não excluir acidentalmente arquivos que contenham "comida" (a menos que esteja excluindo tudo o que contém comida é o que você deseja).

 $ find -type f -exec grep -q "\<foo\>" {} \; -delete

agudamente, redirecionaria a saída antes de excluir para poder revisar antes de excluir:

 $ find -type f -exec grep -q "\<foo\>" > /tmp/list_of_files_to_delete

Assim que puder postar comentários, você deve postar coisas assim como comentários.
FSMaxB

sim, tentei primeiro, mas depois percebi que ainda não tenho permissão para postar comentários.
precisa
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.