I learned when I use command, double quoting treat all things as character except $, `, \ .

But, when use command like find -type f -name "*.jpg" *.jpg is inside double quotes. Then, it means we want to treat * and . as just a character. So, the find command should output regular file which has name *.jpg as it says, not pathname expansion implemented.

If we want to do pathname expansion, I think I have to do type command find -type f -name *.jpg(without double quoting).

But, the result is same. Why use double quoting in this command?


There is a subtlety to how wildcard expansion works. Change to a directory which contains no .jpg files and type

echo *.jpg

and it will output


In particular, the string *.jpg is left unmodified. If, however, you change to a directory containing .jpg files, for example suppose we have two files: image1.jpg and image2.jpg, then the echo *.jpg command will not output

image1.jpg image2.jpg

and the *.jpg gets expanded.

If you type

find . -name *.jpg

and there are no .jpg files in the directory you are when you type this, then find will receive the arguments ".", "-name" and "*.jpg". If, however, you type this command in a directory containing .jpg files, say image1.jpg and image2.jpg, then find will receive the arguments ".", "-name", "image1.jpg" and "image2.jpg", so will in effect run the command

find . -name image1.jpg image2.jpg

and find will complain. What can be really confusing if you omit the quotes is if there is a single .jpg file (say image1.jpg). Then the wildcard expansion will result in

find . -name image1.jpg

and the find command will find all files whose basename is image1.jpg.

Aside: This does lead to a useful bash idiom for seeing if any files match a given pattern:

if [ "$(echo *.jpg)" = "*.jpg" ]; then
    # *.jpg has no matches
    # *.jpg has matches

though be warned that this will not work if there is a file called '*.jpg' in the current directory. To be more watertight, you can do

if [ "$(echo *.jpg)" = "*.jpg" ] && [ ! -e "*.jpg" ]; then
    # *.jpg has no matches
    # *.jpg has matches

(While not directly relevant to the the question, I added this since it illustrates some of the aspects of how wildcard expansion works.)

  • 1
    That bash idiom is somewhat horrifying. – Wildcard Feb 20 '16 at 0:31
  • 1
    The rest of the answer is good info but doesn't fully answer the question; PSkocik's answer does. The point that find does pattern matching, not glob expansion, is the key. So you need to prevent your shell from doing glob expansion so find receives the pattern you intend. – Wildcard Feb 20 '16 at 0:34

You need to escape the asterisk in the name pattern because find wants to do its own glob expansion in all the various directories it searches. If left unescaped, the * would get expanded by the shell, and for the current directory only. That would likely yield an illegal find invocation.

  • So, if I use double quotes outside of name pattern, then find command internally expands double quoted strings? (I mean just send double quoted string to find command, and find command does its own expansion?) – A.Cho Feb 19 '16 at 16:49
  • Quotes are a shell thing. They don't get passed to the invoked program/function/script. When you do cmd '*.jpg' then *.jpg gets passed. If you don't quote it, shell will expand it and instead of *.jpg the expanded list of files will get passed. – PSkocik Feb 19 '16 at 16:54
  • 1
    PSkocik - maybe a better word would be "escape"... find . -name \*.jpg or find . -name '*.jpg' work equally well. The idea here is that find does pattern matching not expansion. – don_crissti Feb 19 '16 at 16:56
  • @don_crissti +1 good point, fixed it. – PSkocik Feb 19 '16 at 16:59
  • Can I understand then, in pattern matching, find command also use wildcard(which is passed through double-quoted string)? – A.Cho Feb 19 '16 at 17:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.