Expected behavior of `find -depth` if execute permission denied for subdirectory

directoryfindpermissions

I'd like to know if I can rely on the behavior I am seeing when using find with -depth option and user does not have execute permission for a subdirectory.

Assume the following directory structure:

drwxrwxrwt. 10 root    root     12288 Mar 14 04:31 .
dr-xr-xr-x. 24 root    root      4096 Dec  6 03:33 ..
drwx------   4 root    root      4096 Mar 14 04:03 jen

Run the following command as non-root user:

find -type d

The output is:

.
./jen
find: `./jen': Permission denied

So find found the directory jen and output that. It then tried to descend into jen, but didn't have permission so it printed the error. The first line above is printed to stdout and the second line to stderr.

Now run the following as non-root user:

find -depth -type d

And the output is:

find: `./jen': Permission denied
.

So the pathname is not output to stdout unless the user has permission to list the contents of the directory.

This output is perfect for what I want to do. However, I'm not sure if this is just a coincidence or not. Can I rely on this behavior?

I'm using GNU findutils 4.4.2. I'm wondering if this behavior is the same across all versions of find. And if not, is it at least the same across all versions of GNU find.

It doesn't matter to me (for this use case) whether or not jen is printed in the first example. I'm just wondering if I can depend on it being excluded when -depth is used. Normally, it's not a good idea to rely on undocumented behavior. But, to me, this side effect makes sense. So I'm thinking that this might be the intended behavior.

The manual says:

— Option: -depth

Process each directory's contents before the directory itself.

This is exactly what I want, but it's not clear that the pathname of the directory itself will be excluded from the output if it doesn't descend into it.

Thanks to a hint from Hauke Laging, I discovered that I can list only directories and explicitly exclude directories where permission to list their contents is denied:

find -type d \( \( -type d \( \! -executable -or \! -readable \) \) -prune -or -print \)

This also has the effect of stopping the "Permission denied" errors because find never tries to descend into a directory if it doesn't have permission.

Unfortunately, there are two reasons why this will not work for my needs.

  • I want the error messages
  • I need the -depth option

Quoting from the manual

If the ‘-depth’ option is in effect, the subdirectories will have already been visited in any case. Hence ‘-prune’ has no effect in this case.

So I am back to where I started.

It's still not clear whether or not "Process each directory's contents before the directory itself." also means "Don't process the directory if you can't process it's contents".

Best Answer

Probably the better approach is to handle such directories explicitly. I don't know whether these are standard features but at least with Gnu find this is possible:

find . \( -type d \( \! -executable -or \! -readable \) \) -prune -or -type d

of course, it is also possible to print a message if a directory is ignored:

find . \( -type d \( \! -executable -or \! -readable \) \) \
  -printf "Permission denied: %p\n" -prune -or -type d -print
Related Question