How does find -name work?

16,009

The parameter passed to -name is a filesystem glob pattern, the same as the you'd enter for other commands, such as ls -l *in.

For each file it finds it compares the basename of the file to the pattern you passed. So when it finds /bin/foobar it compares foobar to *in, doesn't match, skips; but with /bin/login it compares login to *in and this does match, and so prints.

Now you need to be careful because *in might be matched on the command line depending on files in the current directory.

So, for example:

$ find /bin -name *in
/bin
/bin/login

$ touch foobarin

$ find /bin -name *in
$ 

Notice the same find command returned two different results.

We can see why if we set the shell to debug mode:

$ rm foobarin 

$ set -x

$ find /bin -name *in
+ find /bin -name '*in'
/bin
/bin/login

$ touch foobarin     
+ touch foobarin

$ find /bin -name *in
+ find /bin -name foobarin

$ 

The lines starting with a + are what the shell interpreted the command entered. We can see that the second find command expanded the *in to match the existing filename.

Because of this it's recommended to quote names

$ find /bin -name '*in'
+ find /bin -name '*in'
/bin
/bin/login
Share:
16,009

Related videos on Youtube

Find
Author by

Find

Updated on September 18, 2022

Comments

  • Find
    Find almost 2 years

    I can't for the life of me figure out how find with the test -name works.

    I run find / -name *in and returns a bunch of results:

    /sbin
    /sbin/sulogin
    /dev/stdin
    

    to name a few.

    It's as if it performed filename expansion, but that happens before the shell runs the command, so that can't be it. Also because I don't have any files in the current directory that match *in. Plus, single quoting *in yields the same results, which further supports that this can't be filename expansion.

    The documentation leads me to believe that find with -name uses regular expressions, but the regex pattern *in doesn't match the results I showed above.

    Can someone enlighten me?

    • mosvy
      mosvy about 5 years
      "It's as if it performed filename expansion, but that happens before the shell runs the command, so that can't be it." But that's exactly what it is! Only that instead of matching the *in pattern against the files from the cwd, it matches it against the the files from the directories it's walking through.
    • mosvy
      mosvy about 5 years
      "The documentation kind of suggests that find with -name uses regular expressions" the documentation does not suggest such thing.
    • Freddy
      Freddy about 5 years
      If you need regular expressions, you can use -regex pattern which is used to match the whole path (including slashes), while -name pattern operates on the filename and uses shell patterns.
  • Find
    Find about 5 years
    Thank you, that's helpful. When you say that we should quote names. Should it be, more precisely, single quote them?
  • Stephen Harris
    Stephen Harris about 5 years
    The quote will depend on how you want the command line to interpret your input, same as everywhere else. So if you're looking for a file called $foo then you may use '$foo' but if you want to expand the variable then you may use "$foo". This isn't specific to the find command, but is how the command line works.
  • Find
    Find about 5 years
    But won't the variable be expanded just like * was when you used single quotes? EDIT: I understand this expansion occurs after the command is ran, contrarily to "regular expansion".
  • Stephen Harris
    Stephen Harris about 5 years
    No; command line globs don't follow variable expansion. eg if we set $ foo='*in' then the command $ find /bin -name "$foo" will give the debug output + find /bin -name '*in' which is exactly what we want.