Search code examples
bashfindquotesquoting

Strange behaviour of find when passing variable parameters


I created a file called foo bar (with the command touch foo\ bar).

Then, in Bash I tried the following commands:

s='"foo bar"'; find $s
s='"foo bar"'; find "$s"
s="foo bar"; find "$s"

With the first one, find looks for files named "foo and then for files named bar".

With the second one, find looks for files named "foo bar".

Both commands fail: find does not find any file.

Finally the third command has the expected behaviour: find looks for foo bar and shows it.

I know it is bad practice not to escape the space character, but can anyone explain me what is going on here? Why doesn't the second command work?


Solution

  • I know it is bad practice not to escape the space character, but can anyone explain me what is going on here? Why doesn't the second command work?

    Because you are looking for something called "foo bar". You quoted too much :)

    By saying:

    s='"foo bar"'
    

    you indicate that the variable $s is in fact "foo bar". That is, the quotes belong in the variable content.

    • When you say:

      find "$s"
      

    you are trying to find those files whose name is exactly "foo bar", with the quotes. Then, if we create a file with this exactly name, it will work:

    $ touch '"foo bar"'
    $ s='"foo bar"'; find "$s"
    "foo bar"
    
    • When you say:

      $ s='"foo bar"'; find $s
      find: ‘"foo’: No such file or directory
      find: ‘bar"’: No such file or directory
      

    You are in fact saying:

    $ find \"foo bar\"
    find: ‘"foo’: No such file or directory
    find: ‘bar"’: No such file or directory
    

    That is, you are using find together with two arguments: "foo or bar". And neither of these files exist. But, again, if you create one of them, voilà!

    $ touch '"foo'
    $ find \"foo bar\"
    "foo
    find: ‘bar"’: No such file or directory
    

    Note the behaviour of find X Y is to look for X and Y:

    $ find a b
    find: ‘a’: No such file or directory
    find: ‘b’: No such file or directory