Execute a command stored into a $variable
I made a script where I wrote:
COMMAND="/usr/bin/exiftool $PATH_NAME" .... code .... $COMMAND
The variable $PATH_NAME is assigned dynamically inside a while loop. The command works fine until it encounters files with spaces (for example PATH_NAME="Add Driver.png"). The console output is:
File not found: ./Add File not found: driver.png
The command should be:
/usr/bin/exiftool ./Add driver.png
I think the problem is given by the spaces in the $PATH_NAME. I tried also to execute directly the command:
eval "/usr/bin/exiftool $PATH_NAME"
But same output error. Any idea to solve the problem? thanks.
Solution 1:
Instead of using simple strings, build your command using arrays. Arrays provide a convenient interface: If a
is an array, then "${a[@]}"
(note the quotes) expands into each element of a
, without additional field splitting or globbing (so spaces, and things like wildcards, should remain intact).
Example:
$ a=(printf "|%s|\n" "foo bar" "*")
$ echo ${a[@]}
printf |%s|\n foo bar bin boot dev etc home lib lib64 lost+found mnt opt proc root run sbin srv sys tmp usr var
Note how the *
was expanded, and how the extra spaces between foo
and bar
were lost. But with the "${a[@]}"
, these are preserved:
$ echo "${a[@]}"
printf |%s|\n foo bar *
This is ideal for building commands. Now, you can do:
$ "${a[@]}"
|foo bar|
|*|
See? The arguments were retained perfectly.
So, do:
COMMAND=(/usr/bin/exiftool "$PATH_NAME")
"${COMMAND[@]}"
Solution 2:
glenn jackman's point is well taken. But, to solve your immediate use case, how about backticks? Like so:
`echo $COMMAND`
For example, this works:
COMMAND='ls /'
`echo $COMMAND`
Solution 3:
For more detailed explanations about how Bash interprets spaces, I recommend to read this: Bash variables and command substitution
Clean solution
Expanding a variable can lead to unexpected and sometimes catastrophic results if the variable contains special characters:
user@host:~$ do_something $some_variable
Expanding a variable within double-quotes can prevent such problems:
user@host:~$ do_something "$some_variable"
Explanation
The case encountered here is described at the end of the post:
The dangers of unquoted variables
In an ideal world, everyone would keep their string values short and without space/newline, or any other special characters.
[...]
But when people start adding special characters to filenames, such as spaces, expanding variables, without the use of double quotes, can be dangerous.
[...]
So the main takeaway here is: double-quote your variable references whenever possible.