I am trying to run a command from a bash script. The command itself has single quotes in it, but I can't get them to work as there are variables inside the single quotes that need to be expanded. Here is the bash script:
#!/bin/bash
if [ "$2" == "PracSci" ];
then
echo "Running tabulate.science.r"
R CMD BATCH --no-save --no-restore --slave '--args $1 $2 $3' tabulate.science.r /dev/tty
else
echo "Running tabulate.r"
R CMD BATCH --no-save --no-restore --slave '--args $1 $2 $3' tabulate.r /dev/tty
fi
When run as ./script.sh 2 Vocab May12
for example, the command itself is run without the variables values.
How can I expand the variables while still getting the command to run?
Just to be clear, the command I am trying to run is:
R CMD BATCH --no-save --no-restore --slave '--args $1 $2 $3' tabulate.r /dev/tty
(including the single quotes in the command).
Thank you!
Short answer: use double-quotes instead of single-quotes (as @Pavel suggested). And when in doubt, use set -x
to find out how the shell is parsing your commands.
Long answer: quotes aren't passed to the command; instead, they are parsed (and removed) by the shell, before the arguments are passed to the command. What they do is to change the way the shell parses what's inside the quotes (generally by suppressing the special meanings of some characters), which means that you need to choose the appropriate quotes to allow the special characters you want parsed, and suppress the ones you want treated as just plain characters. For instance, consider the following command:
R CMD BATCH --no-save --no-restore --slave '--args 2 Vocab May12' tabulate.r /dev/tty
The shell will ignore the special meanings of all characters in the single-quoted section of the command. The only characters with any special meaning there are the spaces, which normally act as separators between arguments; in this case, the single-quotes make the shell treat them as part of a single argument. These other commands:
R CMD BATCH --no-save --no-restore --slave "--args 2 Vocab May12" tabulate.r /dev/tty
R CMD BATCH --no-save --no-restore --slave --args' '2' 'Vocab' 'May12 tabulate.r /dev/tty
R CMD BATCH --no-save --no-restore --slave --args\ 2\ Vocab\ May12 tabulate.r /dev/tty
...all do exactly the same thing, because they all (one way or another) get the shell to treat the spaces as part of an argument, rather than separators between arguments.
Now, let's look at the command that isn't working for you:
R CMD BATCH --no-save --no-restore --slave '--args $1 $2 $3' tabulate.r /dev/tty
The problem is that while the single-quotes are suppressing the special meaning of the spaces (as you want), they're also suppressing the special meaning of the $
s (which you don't want). So you need something more selective. One option would be to quote/escape the spaces but leave the $1
etc unquoted:
R CMD BATCH --no-save --no-restore --slave --args' '$1' '$2' '$3 tabulate.r /dev/tty
R CMD BATCH --no-save --no-restore --slave --args\ $1\ $2\ $3 tabulate.r /dev/tty
(note that both of these commands do exactly the same thing.) These would mostly work, but have a bit of a potential for trouble: the shell will replace $1
etc with the arguments to the script, but then it does some additional parsing on them: looking for spaces to use as argument separators, wildcards to do filename matching on, etc. All things I'm pretty sure you don't want -- although since the arguments probably won't contain any special characters this probably won't be an issue. Probably.
The best option I see is to simply use double-quotes:
R CMD BATCH --no-save --no-restore --slave "--args $1 $2 $3" tabulate.r /dev/tty
Double-quotes suppress the special meaning of spaces(as you want), allow $
to trigger variable expansion (also as you want), BUT prevent any further parsing once the variables have been expanded (also probably what you want). Spaces or other funny characters in arguments might still cause trouble within the R script, but at least this prevents them from causing trouble before the R script is even started.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With