10

find is always a complete mystery to me whenever I use it; I just want to exclude everything under /mnt (I am in bash on Ubuntu 20.04 on WSL so don't want it to search in the Windows space) from my search, but find just blunders into those directories completely ignoring me. I found syntax from this page. https://stackoverflow.com/questions/4210042/how-to-exclude-a-directory-in-find-command and tried all variations - all failed.

sudo find / -name 'git-credential-manager*' -not -path '/mnt/*'
sudo find / -name 'git-credential-manager*' ! -path '/mnt/*'
sudo find / -name 'git-credential-manager*' ! -path '*/mnt/*'

When I do this, it just blunders into /mnt and throws errors (which is really frustrating as the syntax above looks clear, and the stackoverflow page syntax seems correct):

find: ‘/mnt/d/$RECYCLE.BIN/New folder’: Permission denied
find: ‘/mnt/d/$RECYCLE.BIN/S-1-5-18’: Permission denied

Can someone show me how to stop find from ignoring my directory exclusion switches?

0

2 Answers 2

18

Find's -path doesn't exclude paths, it means "do not report any matches whose name matches this path". It will still descend into the directories and will search them. What you want is -prune (from man find):

       -prune True;  if  the file is a directory, do not descend into it.  If
              -depth is given, then -prune has no  effect.   Because  -delete
              implies  -depth, you cannot usefully use -prune and -delete to‐
              gether.  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

So, you want:

sudo find / -path '/mnt/*' -prune -name 'git-credential-manager*' 

Although, based on what you're trying to exclude, it might be easier to use -mount (GNU find) or -xdev (others):

From man find:

-mount Don't descend directories on other filesystems. An alternate name for -xdev, for compatibility with some other versions of find.

So:

sudo find / -mount -name 'git-credential-manager*' 
3
  • 2
    The -mount switch works for me perfectly. The only problem with the find man page is that it is crazy long and complex, but find is quite a complex app I guess. Thanks for the useful options like prune etc. 👍
    – YorSubs
    Commented Oct 28, 2021 at 15:37
  • 5
    @YorSubs It is entirely normal that you don't easily get it! I have been using various flavors of Linux as my main (only) operating system at work and home since 1998, and I spend most of my time in the command line. I still don't fully grasp all the intricacies of find.
    – terdon
    Commented Oct 28, 2021 at 15:42
  • 2
    @terdon Imagine developing it... Commented Oct 28, 2021 at 15:48
11

It doesn't ignore the option. The -path predicate is evaluated for each and every file encountered, and for the files in that tree, it just fails. It doesn't affect how find walks the directory tree, and you could have something like find . ! -path "./foo/*" -o -name '*.txt' which would match everything outside foo, but also files matching *.txt within it.

The GNU man page is rather clear on what to do here, use -prune instead:

-path pattern
... 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

You must log in to answer this question.

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