andimeier
andimeier

Reputation: 1253

Execute command parsed from a string containing arguments with spaces

I would like to execute a command which is given by a variable (Variable cmd in this example):

cmd="echo 'First argument'"
$cmd

Expected result would be:

First argument

BUT ... actual result is:

'First argument'

What? I don't understand why I can see single quotes in the output. After all, if the command (=content of variable $cmd) would be issued directly, then no quotes leak into the output, it behaves as desired:

$ echo 'First argument'
First argument

To illustrate what I am trying to achieve in real life: in my deploy script there is a code block like this (strongly simplified, but you get the point):

#!/bin/bash
function execute {
    cmd=$1
    echo "Executing $cmd ..."

    # execute the command:
    $cmd
}    

VERSION=1.0.2
execute "git tag -a 'release-$VERSION'"

Now, Git would create a tag which contains single quotes:

git tag
'1.0.2'

which is not what I want ...

What to do?

(Bash version: GNU bash 3.1.0)

(I found a very similar issue, here, but the answer would not apply to my problem)

Upvotes: 0

Views: 3238

Answers (2)

Mark Setchell
Mark Setchell

Reputation: 207465

I think this is what you want:

cmd="echo 'First arg'"
eval $cmd
First arg

Upvotes: 1

konsolebox
konsolebox

Reputation: 75488

cmd="echo 'First argument'"
$cmd

What happens there is word splitting and the actual resulting command is:

echo "'First" "argument'"

Double-parsing with the single quotes inside would never happen.

Also, it's better to use arrays:

#!/bin/bash

function execute {
    cmd=("$@")  ## $@ is already similar to an array and storing it to another is just optional.
    echo "Executing ${cmd[*]} ..."

    # execute the command:
    "${cmd[@]}"
}    

VERSION=1.0.2
execute git tag -a "release-$VERSION"

For eval is a difficult choice in that kind of situation. You may not only get unexpected parsing results, but also unexpectedly run dangerous commands.

Upvotes: 3

Related Questions