My Bash script sends a set of (multiple) parameters to a C program.
This is my C program :
$ cat main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main( int argc, char **argv )
{
printf("Parameter 1 is: %s \n", argv[1]);
printf("Parameter 2 is: %s \n", argv[2]);
return 0;
}
Once compiled (as MyCProgram
), it behaves OK:
MyCProgram -f "/path/to/file/with spaces"
Parameter 1 is: -f
Parameter 2 is: /path/to/file/with spaces
But, when trying to send to it parameters via shell variable :
$ var='-f "/path/to/file/with spaces" '
$ MyCProgram $var
Parameter 1 is: -f
Parameter 2 is: "/path/to/file/with
$ MyCProgram "$var"
Parameter 1 is: -f "/path/to/file/with spaces"
Parameter 2 is: (null)
$ MyCProgram '$var'
Parameter 1 is: $var
Parameter 2 is: (null)
$ MyCProgram "$(echo $var)"
Parameter 1 is: -f "/path/to/file/with spaces"
Parameter 2 is: (null)
$ MyCProgram "$(echo "$var")"
Parameter 1 is: -f "/path/to/file/with spaces"
Parameter 2 is: (null)
$ MyCProgram "$(echo '$var')"
Parameter 1 is: $var
Parameter 2 is: (null)
$ MyCProgram '$(echo "$var")'
Parameter 1 is: $(echo "$var")
Parameter 2 is: (null)
$ var="-f '/path/to/file/with spaces' "
$ MyCProgram $var
Parameter 1 is: -f
Parameter 2 is: '/path/to/file/with
How can I obtain the proper behavior , this is, same as when run without shell variables?
Notes :
Upon Craig Estey answer , this works fine:
$ var=(-f "/file with spaces")
$ MyCProgram "${var[@]}"
This method works, but only if I manually (explicitly) assign the value to var
. Assuming var is already assigned (ie: via input read or file read), I would say the problem here is transferring it to a bash array variable. So:
$ var='-f "/file with spaces"'
$ var2=( $var )
$ MyCProgram "${var2[@]}"
Parameter 1 is: -f
Parameter 2 is: "/file
The problem is still there.
You probably want to use a bash array variable
Do the following to set the variable:
var=(-f "/file with spaces")
Then, invoke your program:
MyCProgram "${var[@]}"
var='-f "/path/to/file/with spaces" '
In this situation, the contents of var
are shell syntax.
To process shell syntax, we can therefore use the eval
function:
eval "MyProgram $var"
This will construct the argument
MyProgram -f "/path/to/file/with spaces"
and then evaluate it as a little shell script.
Needless to say, there are security implications. We are trusting the inputs that went into the construction of script contained in var
. For that reason, eval
should be shunned as much as possible.
When we introduce eval
, we have to think about: who controls the inputs that go into the string being passed to eval
? Could someone malicious sneak in something to get eval
to run arbitrary code?
If the construction of var
is under your control, and either has no untrusted inputs, or those inputs are dealt with properly, then this may be an appropriate solution.
Without specifying delimiter in xargs
, it parses "
and '
quotes and backslashes, so assuming var
content is sane, you could do:
<<<"$var" xargs MyProgram
You could write your own tokenizer for var
content - ex. split it on the first space and then remove the "
quotes.
# split var on space
IFS=' ' read -r option file <<<"$var"
# remove quotes from file - ie. remove last and first character
file=${file%\"}
file=${file#\"}
# run your program
MyProgram "$option" "$file"
Would you please try the following:
var='-f "/path/to/file/with spaces" '
declare -a var2="( $var )"
./MyCProgram "${var2[@]}"
Output:
Parameter 1 is: -f
Parameter 2 is: /path/to/file/with spaces
Note that declare
may have a potential risk as eval
and you will need to take a control so that an arbitrary string is not fed to declare
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.