6

I need to generate a file list from a disk volume. Some of the directories (all hidden directories under the root directory) have strange permissions that causes find to complain.

I try to exclude all these paths, but one directory still complains:

find . -type f -not -path './.*/*'
find: ./.DocumentRevisions-V100: Permission denied

The rights are like this (set so by the operating system, so I assume they shouldn't be messed with).

d--x--x--x root  wheel   .DocumentRevisions-V100

How do I change the find statement to effectively omit all the hidden directories as to not complain. (I do not want to do 2>/dev/null as I want to know about other problems).

forthrin
  • 2,289
  • This set of permissions will prevent you from browsing the directory's contents (hence the Permission denied error) but it allows you to descend through the directory and access items within it if you already know the file or path name beneath it (and have the appropriate permissions there), so it can provide a useful layer of security. – Randall Aug 23 '18 at 16:01

3 Answers3

7

With GNU find or any other find that supports the -readable and -executable predicates:

find . -type d ! \( -readable -executable \) -prune -o -type f -not -path './.*/*' -print

First we prune directories that aren't traversable. If that condition doesn't apply, try the other condition(s).

If your find doesn't have these options, you can match against the file permissions.

find . -type d ! -perm -u+rx -prune -o -type f ! -path './.*/*' -print
ntc2
  • 146
3

The syntax of find is a strange beast indeed. I think you might have success with

find . -path './.*' -prune -o -type f -print

per the find(1) man page:

To ignore a whole directory tree, use -prune rather than checking every file in the tree. For example, to skip the directory 'src/emacs' and all files and directories under it, and print the names of the other files found, do something like this:

find . -path ./src/emacs -prune -o -print
msw
  • 10,593
1
u='-user "$USER"'
g='\('$(IFS=\ ;printf " -group %d " $(id -G))'\)'
eval "find / $u \( -perm -u=rx -o -prune \) -o \
             $g \( -perm -g=rx -o -prune \) -o \
                   -perm -o=rx -o -prune" | wc -l

That works. Because file permissions are always evaluated at the most specific level possible, you don't have to -or too much. If a file is owned by someuser and is readable by others and groups but not by the owner then someuser still cannot read it. And so you just need to start at the most specific permission match and work your way down from there, -pruning all the while.


find: `/proc/3379/task/3379/fd/5': No such file or directory
find: `/proc/3379/task/3379/fd/5': No such file or directory
find: `/proc/3379/task/3379/fd/5': No such file or directory
find: `/proc/3379/task/3379/fd/5': No such file or directory
find: `/proc/3379/task/3379/fdinfo/5': No such file or directory
find: `/proc/3379/task/3379/fdinfo/5': No such file or directory
find: `/proc/3379/task/3379/fdinfo/5': No such file or directory
find: `/proc/3379/task/3379/fdinfo/5': No such file or directory
find: `/proc/3379/fd/5': No such file or directory
find: `/proc/3379/fd/5': No such file or directory
find: `/proc/3379/fd/5': No such file or directory
find: `/proc/3379/fd/5': No such file or directory
find: `/proc/3379/fdinfo/5': No such file or directory
find: `/proc/3379/fdinfo/5': No such file or directory
find: `/proc/3379/fdinfo/5': No such file or directory
find: `/proc/3379/fdinfo/5': No such file or directory
327652

As you can see, at no point is there a permissions issue, just a few occasionally race issues to do with /proc - which is unavoidable when spawning files to read files.

mikeserv
  • 58,310