Pourquoi 'find -delete' supprime-t-il récursivement tous les fichiers d'un répertoire

15

Donc, le comportement suivant d'Unix Find me coûte très cher:

> touch foo
> touch bar
> ls  
bar  foo
> find . -name '*oo' -delete
> ls
bar
> touch baz
> ls
bar  baz
> find . -delete -name '*ar'
> ls
> #WHAAAT?

Comment ça peut vouloir dire quelque chose?

mszep
la source
2
Cette question est liée, pourrait être intéressante pour les futurs lecteurs. unix.stackexchange.com/questions/101282/…
Bernhard

Réponses:

14

La ligne de commande de find est constituée de différents types d'options, qui sont combinés pour former des expressions.

L' findoption -deleteest une action.
Cela signifie qu'il est exécuté pour chaque fichier correspondant jusqu'à présent.
Comme première option après les chemins, tous les fichiers sont mis en correspondance ... oups!

C'est dangereux - mais la page de manuel contient au moins un gros avertissement :

De man find:

ACTIONS
    -delete
           Delete  files; true if removal succeeded.  If the removal failed, an
           error message is issued.  If -delete fails, find's exit status  will
           be nonzero (when it eventually exits).  Use of -delete automatically
           turns on the -depth option.

           Warnings: Don't forget that the find command line is evaluated as an
           expression,  so  putting  -delete first will make find try to delete
           everything below the starting points you specified.  When testing  a
           find  command  line  that  you later intend to use with -delete, you
           should explicitly specify -depth in order to avoid later  surprises.
           Because  -delete  implies -depth, you cannot usefully use -prune and
           -delete together.


De plus haut en man find:

EXPRESSIONS
    The expression is made up of options (which affect overall operation rather
    than  the  processing  of  a  specific file, and always return true), tests
    (which return a true or false value), and actions (which have side  effects
    and  return  a  true  or false value), all separated by operators.  -and is
    assumed where the operator is omitted.

    If the expression contains no actions other than  -prune,  -print  is  per‐
    formed on all files for which the expression is true.


En essayant ce que findfera une commande:

Pour voir à quoi ressemble une commande

find . -name '*ar' -delete

supprimera, vous pouvez d'abord remplacer l'action -deletepar une action plus inoffensive - comme -flsou -print:

find . -name '*ar' -print

Cela imprimera les fichiers affectés par l'action.
Dans cet exemple, -print peut être omis. Dans ce cas, il n'y a pas d' action du tout, donc on ajoute implicitement la plus évidente: -print. (Voir le deuxième paragraphe de la section "EXPRESSIONS" citée ci-dessus)

Volker Siegel
la source
Je suppose que j'étais juste un idiot pour ne pas avoir lu le manuel en premier .. Mais il semblait si simple d'ajouter simplement le -deletedrapeau :-) Mais y a-t-il une raison pour laquelle quelqu'un ferait jamais find . -deleteplutôt que rm -rf .? Ou est-ce simplement la façon dont il findanalyse et traite ses arguments?
mszep
1
Oh, je suis tout à fait d'accord pour dire que la syntaxe est très dangereuse - mais c'est difficile à éviter, car c'est juste un cas particulier de la syntaxe d'expression de ligne comman de find, qui est extrêmement puissante. Puissant comme dans " Une tronçonneuse puissante ".
Volker Siegel
la page de manuel citée ne dit- warning: use -depth when testing stuff you later want to -deleteelle pas ce que vous n'avez pas fait dans votre exemple pratique?
pqnet
Oh, c'est vrai - le problème est l'en-tête - je voulais illustrer l'utilisation de l'impression à la place de -delete comme une -noption; La première commande ne devrait évidemment pas avoir d’utilité pratique; Je vais le changer.
Volker Siegel
9

Dans l' findordre des arguments, ça compte beaucoup.

Les arguments peuvent être des options, des tests et des actions. Vous devez généralement utiliser les options d'abord, puis les tests, puis les actions.

Parfois, findmême vous met en garde contre un éventuel mauvais ordre (par exemple lorsque vous utilisez -maxdepthaprès d'autres arguments), mais d'autres, il semble que non.

Qu'est find . -delete -name '*ar'- ce que c'est:

  1. Recherche des fichiers et des répertoires sur le répertoire actuel.
  2. Les supprime TOUS comme ils sont trouvés!
  3. Vérifie ensuite s'ils sont nommés comme '* ar' (cette partie n'a plus d'effet maintenant).

Ce que vous voulez probablement faire, c'est:

find -name '*ar' -delete

Cela, pour chaque fichier, verra s'il correspond '*ar', et seulement s'il remplit la condition, il supprimera le fichier.

Désolé si vous l'avez découvert trop tard.

LatinSuD
la source