Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invoking a command line with spaces from a variable in a Bash script [duplicate]

Tags:

bash

I thought it would be easy, but I already wasted a few hours on this.

I want to run the following CMake command from inside a Bash script. In a terminal I would type

cmake -G "Unix Makefiles" .

and it works. If I copy this exactly inside the Bash script it works as well.

But the script is meant to work on multiple platforms, and it could be "MSYS Makefiles" instead of "Unix Makefiles". Therefore, I want to put the command in a variable, where the contents depends on the platform and execute it. However, this is where I got stuck. I tried every combination of single/double quotes I could think of, but I got nowhere.

I want something along the lines

c="cmake . -G \"Unix Makefiles\""
exec $c

but it always results in some variation of the following:

CMake Error: Could not create named generator "Unix

I realize that I could do

if test [... this is Unix ...]
    cmake . -G "Unix Makefiles"
else
    cmake . -G "MSYS Makefiles
fi

but since this call has to be made several times I'd rather avoid it.

Any suggestion?

like image 610
Alain Avatar asked Apr 20 '11 13:04

Alain


People also ask

How do you pass arguments with spaces to a shell script?

Arguments can be passed to the script when it is executed, by writing them as a space-delimited list following the script file name. Inside the script, the $1 variable references the first argument in the command line, $2 the second argument and so forth. The variable $0 references to the current script.

Does bash ignore whitespace?

Bash uses whitespace to determine where words begin and end. The first word is the command name and additional words become arguments to that command.

How do you represent a space in bash script?

Save this question. In a bash script, we can escape spaces with \ .

Do spaces matter in shell script?

The lack of spaces is actually how the shell distinguishes an assignment from a regular command. Also, spaces are required around the operators in a [ command: [ "$timer"=0 ] is a valid test command, but it doesn't do what you expect because it doesn't recognize = as an operator.


2 Answers

It is best not to use eval unnecessarily. Try not to put the command inside a variable. You can put the options as a variable though:

if [ ... ]
  string="Unix makefiles"
else
  string="MSYS Makefiles"
else
  string="...."
fi
cmake -G "$string" # Just call the command normally
like image 89
bash-o-logist Avatar answered Oct 11 '22 23:10

bash-o-logist


Use eval to tell the shell to parse the command-line anew:

c="cmake . -G \"Unix Makefiles\""
eval "$c"

Alternatively, I like using arrays to avoid the unnecessary backslashes and eval:

# Store command in 4-element array: ["cmake", ".", "-G", "Unix Makefiles"].
# No backslash escapes needed.
c=(cmake . -G "Unix Makefiles")

# Ugly syntax for expanding out each element of an array, with all the spaces and
# quoting preserved to ensure that "Unix Makefiles" remains a single word.
"${c[@]}"
like image 41
John Kugelman Avatar answered Oct 12 '22 00:10

John Kugelman