So the following behaviour of unix find just cost me dearly:
> touch foo > touch bar > ls bar foo > find . -name '*oo' -delete > ls bar > touch baz > ls bar baz > find . -delete -name '*ar' > ls > #WHAAAT?
How does this make sense?
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It only takes a minute to sign up.Sign up to join this community
The command line of find is made from different kinds of options, that are combined to form expressions.
-delete is an action.
That means it is executed for each file matched so far.
As first option after the paths, all files are matched... oops!
It is dangerous - but the man page at least has a big warning:
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.
From further up in
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.
On trying out what a
find command will do:
To see what a command like
find . -name '*ar' -delete
will delete, you can first replace the action
-delete by a more harmless action - like
find . -name '*ar' -print
This will print which files are affected by the action.
In this example, the -print can be left out. In this case, there is not action at all, so the most obvious is added implicitly:
find argument order matters, a lot.
Arguments can be options, tests and actions. You should typically use options first, then tests, then actions.
find even warns you about a possible bad ordering (for example when you use
-maxdepth after other arguments), but others it seems it doesn't.
find . -delete -name '*ar' does is:
What you probably want to do is:
find -name '*ar' -delete
This will, for every file, see if it matches
'*ar', and only if it satisfies the condition it will delete the file.
Sorry if you found out too late.