The -delete
action does not remove directories, so why does find -delete
need to imply -depth
?
For GNU utilities, the reference documentation is the utilities’ info files, not their man pages; as happens in some cases, the man page quoted in the question is misleading. find -delete
can remove directories:
Delete files or directories; true if removal succeeded. If the removal failed, an error message is issued.
-delete
has always supported deleting directories, ever since its introduction in GNU find
in 2004 (findutils
4.2.3).
Deleting directories is the reason -delete
implies -depth
: it can only delete directories if it has previously emptied them. -delete
on directories is equivalent to rmdir
, not rm -rf
.
The net effect of find /path -type f -delete
and find /path -type f -exec rm -f {} +
is the same because both find
invocations limit their actions to files. Since only files are deleted, the order in which they are deleted has no effect on find
’s traversal. When deleting directories, find
’s traversal does come into play. If -delete
is used on directories, then a directory’s children must all have been processed before the directory itself can be deleted; this is where -depth
is useful. If rm -rf
is used on directories being traversed, then find
must be told about the deletion before it attempts to traverse a deleted directory’s children; this is one instance where -prune
is useful.
One could imagine special-casing it so that it doesn’t set -depth
if it’s not going to delete directories, but that’s impossible to determine ahead of time in the general case. (-depth
is an option, not an action; it needs to be set before the first action is actually processed.)
Alternatively, as has been proposed in the past, one could imagine not having any special handling of -delete
at all, and letting the user take care of ensuring that -delete
can do its job when it has to. However this would break backwards compatibility and compatibility with other implementations which have copied -delete
. See also the discussion in Savannah bug #20865.
GNU findutils
explicitly checks for -delete
combined with -prune
since version 4.3.11, and aborts if -depth
hasn’t been explicitly set. The comments note that
We only get away with this because the -delete
predicate is not
in POSIX. If it was, we couldn't issue a fatal error here.
As discussed in Why did find with -delete erase the files in my /save/ directory when find without delete was not able to locate them?, if you’re using GNU find
, you should use -execdir rm {} +
instead of -exec rm {} +
.
-depth
option is a bit unluckily named,find
doesn't do a width-first (or breadth-first) walk even without it. Defaultfind
would walka
,a/b
,a/b/123
thena/c
, while a proper breath-first search would walk the tree in the ordera
,a/b
,a/c
, thena/b/123
, with the whole of the second level first, before descending to the third level. The-depth
only changes if the inner nodes are processed before (preorder) or after (postorder) of their children, i.e. it turns the order toa/b/123
,a/b
,a/c
,a
, with the whole subtree ofa/b
still processed beforea/c
.rm -rf
. If I want to select particular files and directories often I'll want to use-prune
, and at that point-delete
is useless to me anywayfind . -empty -delete
will remove directories which become empty after discovering all existing files in them are empty, and leave alone directories with non-empty files. That's not simply achieved with justrm -rf
because-empty
would not see the directories as empty when they contain empty files. I'll admit it would be no hassle to include-depth
in the command though.