6

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.

2
  • Yes, tried but same error.
    – Labo29
    Commented Apr 26, 2016 at 18:53
  • 4
    This problem is BashFAQ50 Commented Apr 26, 2016 at 18:54

3 Answers 3

8

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[@]}"
1

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`
1
  • 2
    -1 Why `echo $COMMAND` and not just $COMMAND? They have the same effect (except for some corner cases of which the echo variant has more). Commented Apr 26, 2016 at 21:01
1

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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .