8

The man page for GNU find clearly warns that using -delete implies -depth. However, I cannot find any explanation for this requirement:

-delete Delete files; true if removal succeeded. If the removal failed, an error message is issued. […] Use of -delete automatically turns on the -depth option.

find --version
find (GNU findutils) 4.8.0

This is implicitly a post-order walk:

find /path -type f -delete

But this is a pre-order walk, the usual method of traversal for find:

find /path -type f -exec rm -f {} +

If I want to use -prune I cannot use -delete and instead I must use the more cumbersome -exec rm {} +, yet the net effect seems the same.

The -delete action does not remove directories, so why does find -delete need to imply -depth?

4
  • 2
    The -depth option is a bit unluckily named, find doesn't do a width-first (or breadth-first) walk even without it. Default find would walk a, a/b, a/b/123 then a/c, while a proper breath-first search would walk the tree in the order a, a/b, a/c, then a/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 to a/b/123, a/b, a/c, a, with the whole subtree of a/b still processed before a/c.
    – ilkkachu
    Jan 8, 2022 at 14:08
  • 1
    It's particularly useful when you want to delete empty files and directories unix.stackexchange.com/a/577868/20140 because the directories may only become empty after deleting empty files. Jan 8, 2022 at 18:35
  • @PhilipCouling if I want to do that there's 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 anyway Jan 8, 2022 at 22:11
  • @roaima look again, the find . -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 just rm -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. Jan 8, 2022 at 22:37

1 Answer 1

13

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 {} +.

2
  • 2
    Thank you. Debian bug report generated Jan 8, 2022 at 17:08
  • 1
    @roaima I imagine the manpage says "files" in the sense of all types of files, including regular, directories, pipes, sockets, etc. Saying "files and directories" makes it sound like there's this grouping called "files" that include regular, pipes, sockets, etc. but not directories, or maybe it's more of a way of ignoring that there's more than just regular files and directories. No perfect terminology for documentation, I guess.
    – JoL
    Jan 8, 2022 at 23:01

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .