Reputation: 72
I'm trying to launch a script with /bin/bash -c
with positional arguments but can't figure out the following issue:
Suppose I have test.sh as follows:
#!/bin/bash
echo $0
echo $1
> ./test.sh a
./test.sh
a
> /bin/bash -c ./test.sh a
./test.sh
Why does the second one return an empty position argument for $1? Based on the man page:
-c If the -c option is present, then commands are read from the first non-option argument command_string. If there are arguments after the command_string, the first argument is assigned to $0 and any remaining arguments are assigned to the positional
parameters. The assignment to $0 sets the name of the shell, which is used in warning and error messages.
It seems like "a" should be assigned to $0 at least, which is not what I saw. /bin/bash -c 'echo $0' a
works as expected. Thanks!
Upvotes: 2
Views: 605
Reputation: 27
bash [long-opt] [-abefhkmnptuvxdBCDHP] [-o option] [-O shopt_option] -c string [argument ...]
-c
supposed to be followed by a string, so you may quote ./test.sh a
like:
$ /bin/bash -c "./test.sh a"
./test.sh
a
Upvotes: 1
Reputation: 22311
The -c
option does not collect all following arguments of the bash command, but just uses the first non-option argument, which in your case is the one immediately following it. I don't see why you want to use -c
here. I would write your command as
/bin/bash test.sh a
Since in this case, no PATH search is involved, you can also omit the ./
part. In fact, test.sh
doesn't even need to be executable here.
Upvotes: 0
Reputation: 126038
The string after -c
acts like a miniature script, and the arguments after that are passed to it as $0
, $1
, $2
, etc. For example:
$ bash -c 'echo "\$0=$0, \$1=$1, \$2=$2"' zero one two
$0=zero, $1=one, $2=two
(Note: it's important that the mini-script is in single-quotes; without them the references to $0
would be expanded by your interactive shell before they even get passed to the bash -c
command.)
In your case, the mini-script runs another script (./test.sh
), but doesn't pass on the arguments. If you wanted to pass them on, you'd do something like this:
$ bash -c './test.sh "$1" "$2"' zero one two
./test.sh
one
If the script had bothered to print its $2
here, it would've gotten "two". It doesn't help to pass on $0
, because for a real script that's automatically set to the actual command used to run the script.
Upvotes: 2