Search code examples
bashdoublefilenamesquotesexecution

Proper use of quotes in a command substitution - how?


In a rather large project, I run into the following problem: while calculating the correct command in a bash script, I don't manage to make the script respect the double quote necessary for single arguments with a blank.

$ ./testo "two three"
ls -l "two three_DD_FF"  # <- Why does it look for two files HERE??
ls: cannot access '"two': No such file or directory
ls: cannot access 'three_DD_FF"': No such file or directory

"two three" is the single argument.

With two_three my code works, as to be expected:

$ ./testo two_three
ls -l "two_three_DD_FF"
ls: cannot access '"two_three_DD_FF"': No such file or directory

And this is the basic generic code that I could come up with:

#!/usr/bin/bash
cmd="ls -l"
trio=""'"'"${1}_DD"
trio="${cmd} ${trio}_FF"'"'""
echo ${trio}
${trio}

(I didn't find a less strange method than the one above for the strangely looking strong quote, but that is not my main concern here.)

What I don't understand is the problem in execution: ls -l "two three_DD_FF" in the line above still leads to searching for two files, despite of the double quotes; while the same line on the command prompt does a job as intended (that is, searching for file "two three_DD_FF":

$ ls -l "two three_DD_FF"
-rw-rw-r-- 1 myhome me 0 Aug 27 13:09 'two three_DD_FF'

That is, the line echo ${trio} shows a correct command (when executed on the command line, at least; while the same command, when executed from within a script, fails. It fails to respect the double quotes for the file name to be searched.

My questions:

  1. Why does the same command fail from within a script?
  2. Of course, how do I rectify the script, so that the call actually results in the correct output?

Solution

  • My recommendation: work with arrays:

    #!/usr/bin/env bash
    cmd=(ls -l)
    trio=( "${cmd[@]}" "${1}_DD_FF" )
    "${trio[@]}"