Sous Linux, comment trouver tous les fichiers contenant une chaîne et les supprimer?

17

Je souhaite supprimer tous les fichiers contenant la chaîne foo. Comment puis-je faire cela en utilisant bash sous Linux?

Kitsos
la source
cette chaîne est son nom de fichier?
rɑːdʒɑ
3
Veuillez clarifier: voulez-vous supprimer les fichiers dont le nom contient foo(par exemple myfoo.jpg), ou les fichiers qui contiennent la séquence d'octets foo(qui peuvent inclure des fichiers binaires qui contiennent justement cette séquence d'octets)?
hammar

Réponses:

33

Voici un moyen sûr:

grep -lrIZ foo . | xargs -0 rm -f --
  • -l imprime les noms de fichiers des fichiers correspondant au modèle de recherche.
  • -reffectue une recherche récursive du modèle foodans le répertoire donné .. Si cela ne fonctionne pas, essayez -R.
  • -I(majuscule i) fait sauter les fichiers binaires comme les PDF.
  • -Z garantit que les noms de fichiers sont terminés à zéro (c'est-à-dire nul) afin qu'un nom contenant un espace blanc ne soit pas interprété de la mauvaise façon (c'est-à-dire comme plusieurs noms au lieu d'un).
  • xargs -0alimente les noms de fichiers de grepà rm -f, en séparant les mots par zéro (nul) octets (rappelez-vous l' -Zoption de grep).
  • --est souvent oublié mais il est très important de marquer la fin des options et de permettre la suppression des fichiers dont le nom commence par -.

Si vous souhaitez voir quels fichiers sont sur le point d'être supprimés, supprimez simplement la | xargs -0 rm -f --pièce et désactivez l' Zoption grep.

Un autre utilisateur a suggéré quelque chose comme ce qui suit, que vous ne devez pas exécuter car il n'est pas sûr:

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

Si j'ai des fichiers ImportantStuffque je ne veux pas supprimer et obsolete ImportantStuffcontenir foo, alors je perds ImportantStuff(et pas obsolete ImportantStuff !) Lorsque j'exécute cette commande, car elle $filesse décompose dans les espaces lorsqu'elle est interprétée. Il est dangereux de mettre une liste de noms de fichiers dans une variable shell scalaire de cette manière.

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

Cela recherche récursivement les fichiers contenant foo. Le second -execn'est exécuté que si le premier se exectermine avec succès, c'est-à-dire s'il grepcorrespond. Dryrun et retirez le echosi la sortie semble correcte.

Ou bien

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

et

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

comme suggéré par Lekensteyn.

Adrian Frühwirth
la source
4
... qui peut être raccourci en: find -type f -exec grep -q 'foo' {} \; -delete(les guillemets autour {}sont redondants, findest également capable de supprimer des fichiers.). Notez que grepaccepte une expression régulière. Si vous souhaitez rechercher foo.bar, échappez à cela ou passez l' -Foption pour traiter le modèle comme littéral.
Lekensteyn
une raison d'utiliser -exec echo rm "{}" \;et non -delete?
vartec
1
@vartec Non, j'utiliserais -delete. Il est juste plus facile de démontrer avec le second -execet l'écho en place.
Adrian Frühwirth
1
Il est plus facile de taper -print(ou -lspour plus de verbosité) que -exec echo rm "{}" \'. Pas besoin d'utilitaires externes.
Lekensteyn
1
si vous utilisez rm {}, utilisez rm - {}, afin que les caractères spéciaux du nom de fichier lui-même ne soient pas interpolés. Par exemple, touchez '-rf /' dans n'importe quel répertoire où vous avez des autorisations d'écriture ...
atk
1

Je ferais ce que dit Adrian,

Mais j'ajouterais des limites de mots autour du foo afin de ne pas supprimer accidentellement les fichiers contenant des "aliments" (à moins qu'il ne supprime tout ce qui contient des aliments, c'est ce que vous voulez.)

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

en fait, je redirigerais la sortie avant de la supprimer afin de pouvoir l'examiner avant de la supprimer:

 $ find -type f -exec grep -q "\<foo\>" > /tmp/list_of_files_to_delete
Petter H
la source
Dès que vous êtes en mesure de publier des commentaires, vous devez publier des choses comme ça en tant que commentaires.
FSMaxB
oui j'ai essayé d'abord mais j'ai réalisé que je ne pouvais pas encore poster de commentaires.
Petter H