Pourquoi find avec -delete a-t-il effacé les fichiers de mon répertoire / save / alors que find without delete n'a pas pu les localiser?


20

Je souhaite supprimer tous les fichiers de l'arborescence de répertoires actuelle, à l'exception de ceux de save. J'ai exécuté cette commande:

 find . \( -name save -prune \) -o -type f -ls | grep /save/

et il n'en a trouvé aucun. Mais quand j'ai exécuté cette commande:

 find . \( -name save -prune \) -o -type f -delete

Tous ces fichiers dans / save / étaient partis. Qu'est-ce que je rate?


4
Aïe ... j'ai appris quelque chose aujourd'hui (grâce à toi). Et je recommande une simple mv save/ ../some/safer/locationavant une telle commande de suppression "générique" (... mais bien sûr, avant votre publication, j'aurais fait la même vérification et rencontré les mêmes problèmes!). Maintenant, allez trouver un bon "undelete" pour le système de fichiers sur lequel les fichiers étaient ^^
Olivier Dulac

3
Ma douleur est votre prévention.
Otheus

1
1000 merci à vous. Code (souvent?) Fonctionne de façon mystérieuse ...
Olivier Dulac


@lesmana J'ai voté pour votre réponse là-bas. malheureusement, ma version de find ne me donne pas un si bel avertissement :(
Otheus

Réponses:


26

-deleteimplique -depthque cela ne fonctionne pas -prune( -depthcommence par les feuilles). Il y a un avertissement à ce sujet dans le manuel de la version GNU ( -deleteest une extension FreeBSD désormais également prise en charge par GNU findet quelques autres implémentations).

info find --index-search=-delete

L'utilisation de l'action '-delete' sur la ligne de commande active automatiquement l'option '-depth' (* notez find Expressions: :). Cela peut être surprenant si vous testiez auparavant avec '-print', il est donc généralement préférable de ne pas oublier d'utiliser explicitement '-depth'.

info find --index-search=-prune

Parce que «-delete» implique «-depth», l'utilisation de «-prune» en combinaison avec «-delete» peut entraîner la suppression de plus de fichiers que vous ne le souhaitiez.

Ici, vous avez la possibilité d'utiliser à la rmplace:

find . -name save -prune -o -type f -exec rm -f {} +

(potentiellement dangereux s'il y a des répertoires accessibles en écriture par d'autres personnes, car on pourrait vous faire supprimer des fichiers en dehors de l'arborescence de répertoires actuelle en remplaçant les répertoires par des liens symboliques pendant que vous exécutez cette commande).

Une alternative plus sûre:

find . -name save -prune -o -type f -execdir rm -f -- {} \;

Cela n'a pas le problème mentionné ci-dessus mais signifie en exécuter un rmpar fichier. Le --est nécessaire pour l'implémentation de FreeBSD, pas celui de GNU qui préfixe les noms de fichiers ./.

Alternativement, comme suggéré par Costas:

LC_ALL=C find . ! -name save ! -path '*/save/*' -type f -delete

(mais qui descend toujours inutilement dans les saverépertoires)

L' LC_ALL=Cest là *correspond donc à n'importe quelle séquence d'octets (même ceux qui ne forment pas de caractères valides dans les paramètres régionaux actuels). Notez que cela affectera la langue des messages d'erreur (l'anglais au lieu de la langue de l'utilisateur).


Quel est le problème de sécurité ici rm?
jrw32982 prend en charge Monica

@ jrw32982, voir edit avec lien vers le manuel de recherche GNU
Stéphane Chazelas
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.