Linux - SoftwareThis forum is for Software issues.
Having a problem installing a new program? Want to know which application is best for the job? Post your question in this forum.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I have a c program that takes multiple arguments (filenames). You can pass in as many arguments as you want. You can run it like,
./myCprogram "My File1" "My File 2"
Now I want to call that from a bash script. My bash script needs to read the arguments from command line and pass them to the c program. I can read the arguments fine but I can't pass them correctly because the arguments have spaces in them.
Right now I am doing something like,
myargs+=" \""$OPTARG"\""
echo $myargs
#Echo prints "My File1" "My File 2"
myCProgram $myargs
This fails. Bash puts ` in spaces.
Then I tried
myCProgram "$myargs"
This fails too as the whole $myargs is passed as single parameter to myCprogram.
THanks guboj. But that will not work for me. The example I gave was a simple one. In reality, my bash script needs to read multiple arguments and call multiple programs passing different arguments to each one. So I can't just pass $@.
#!/bin/bash
# 2.sh
while [ ! -z "$1" ]; do echo "\"$1\""; shift; done
The fact that 2.sh is another script or a C program shouldn't matter. The list is passed as a list, with al the members intact, hence the result of running this:
Code:
./1.sh asdf ñklj poiu rqwer piupo "foo fight"
Would be:
Code:
"asdf"
"ñklj"
"poiu"
"rqwer"
"piupo"
"foo fight"
As you see, the arguments are ok. Just change the while loop with whatever, and send each argument to whatever place it needs to be. Isn't that what you need?
Sorry if I wasn't clear. I have no issues reading and echoing all the arguments in my script. But its passing them correctly to a different program thats giving me problems.
Inside the script, I need to call two different programs
./myProgramA "My Arg 1" "My arg4" "My arg 5" #All parameters with -a
./myProgramB "My Arg 2" "Myarg3" #All arguments with -b
As you can see I can't just pass $@. I need to first parse all the arguments (which I can do correctly) and then disperse them seperately to appropriate program. . But no I need to
myScript -a "My Arg 1" -b "My Arg 2" -b "Myarg3" -a "My arg4" -a "My arg 5"
So I tried
programAArgs=" "
programBArgs=" "
while getopts "a:b:" Option
do
case $option in
a )
programAArgs=" \""$OPTARG"\""
;;
b )
programBArgs=" \""$OPTARG"\""
;;
esac
done
echo $programAArgs #"My Arg 1" "My arg4" "My arg 5"
echo $programBArgs #"My Arg 2" "Myarg3"
./myProgramA $programAArgs #This fails. Bash puts ` at blanks
./myProgramA "$programAArgs" #This fails too as all of "My Arg 1" "My arg4" "My arg 5" is passed as one single argument to myProgramA not as 3 arguments
I see. I now understand what the problem is. Well, then using an alternative IFS at kenoshi said above is the easiest way to go. Sorry for the misunderstanding.
Thanks. I looked at kenoshi's solution. Its not clear to me how I can use it. I am new to scripting so excuse my ignorance. I am still trying to understand his solution.
The whole trick would be based on using any other arbitrary character as a field separator, kenoshi uses the colon ":". To specify the field separator you use the IFS variable. So, in the first script you parse everything and save the parameters on strings. Each string will contain an arbitrary number of parameters separated by the ":" (or whatever). Then you can send those strings to a second script, to a function, or wherever, just remember to set IFS before that, so this list of elements separated by : will be interpreted as a list of separated entities (arguments).
This is a quick example and I didn't even test it, but I think it should work at least for the most part, and it will illustrate a couple of example functions
Code:
#!/bin/bash
# a.sh
IFS=":"
_foonction() {
args=("$@")
i=${#args[*]}
while [ "$i" -gt "0" ]; do
echo "Argument $i is ${args[$((i-1))]}"
((i--))
done
}
foonction() {
touch "$@"
}
while [ ! -z "$1" ]; do
case "$1" in
-a) if [ -z "$a_params" ]; then
a_params="$2"
else
a_params="$a_params:$2"
fi
shift
;;
-b) if [ -z "$b_params" ]; then
b_params="$2"
else
b_params="$b_params:$2"
fi
shift
;;
*) if [ -z "$z_params" ]; then
z_params="$1"
else
z_params="$z_params:$1"
fi
;;
esac
shift
done
echo "a_params=$a_params"
echo "=================="
_foonction $a_params
echo
echo "b_params=$b_params"
echo "=================="
_foonction $b_params
echo
echo "z_params=$z_params"
echo "=================="
echo " touch'ing some files:"
foonction $z_params
ls -l $z_params
echo
See how in one function I use the kenoshi's snippet, to illustrate how would I use that list on another bash script (or function, it's the same), and in another function I illustrate how an external command or tool can also take approach of the IFS thing. In this case it's "touch", but it could also be your external program or another script. I hope this makes sense. Remember, it's untested so don't go mad if it doesn't work correctly (though it should).
If you change the IFS to “ (a double quotation mark), your script will work with a couple of modifications:
Code:
programAArgs=""
programBArgs=""
while getopts "a:b:" Option
do
case $option in
a )
programAArgs+="\""$OPTARG"" # remove trailing double quote – two quotes together will give you a blank field
;;
b )
programBArgs+="\""$OPTARG"" # same as above
;;
esac
done
echo $programAArgs # "My Arg 1"My arg4"My arg 5 - Pretty ugly but you don't need to output it
echo $programBArgs # "My Arg 2"Myarg3
IFS=”\”” # set the IFS to a double quote
./myProgramA$programAArgs # note: no space between program name and arguments so there is only one string for bash to parse
The content of the string executed by bash is:
Code:
./myProgramA”My Arg 1"My arg4"My arg 5
and bash will separate it at the double quotes
Last edited by norobro; 04-07-2009 at 07:32 PM.
Reason: Corrected typo IFD->IFS in comment
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.