LinuxQuestions.org
Help answer threads with 0 replies.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Software
User Name
Password
Linux - Software This 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

Reply
 
Search this Thread
Old 04-06-2009, 04:50 PM   #1
msreddy999
LQ Newbie
 
Registered: Apr 2004
Posts: 6

Rep: Reputation: 0
bash pass multiple arguments with spaces


Hi,

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.

How can I fix this.

Thanks,
MSR
 
Old 04-06-2009, 05:29 PM   #2
i92guboj
Gentoo support team
 
Registered: May 2008
Location: Lucena, Cˇrdoba (Spain)
Distribution: Gentoo
Posts: 4,040

Rep: Reputation: 373Reputation: 373Reputation: 373Reputation: 373
Try passing the list as "$@"
 
Old 04-06-2009, 05:32 PM   #3
msreddy999
LQ Newbie
 
Registered: Apr 2004
Posts: 6

Original Poster
Rep: Reputation: 0
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 $@.
 
Old 04-06-2009, 05:34 PM   #4
kenoshi
Member
 
Registered: Sep 2007
Location: SF Bay Area, CA
Distribution: CentOS, SLES 10+, RHEL 3+, Debian Sarge
Posts: 159

Rep: Reputation: 32
If you have space in your args, use a different default delimiter, for example:

args.sh
Code:
OFS=$IFS
IFS=':'
optargs="a:b:c d:e f"
./cprog.sh $optargs
cprog.sh
Code:
args=("$@")
i=${#args[*]}
while [ "$i" -gt "0" ] ; do
        echo "Argument $i is ${args[$((i-1))]}"
        ((i--))
done
Executing args.sh results in:
Code:
Argument 4 is e f
Argument 3 is c d
Argument 2 is b
Argument 1 is a
Probably better ways to do this, hope this helps.

Last edited by kenoshi; 04-06-2009 at 05:37 PM.
 
Old 04-06-2009, 05:40 PM   #5
i92guboj
Gentoo support team
 
Registered: May 2008
Location: Lucena, Cˇrdoba (Spain)
Distribution: Gentoo
Posts: 4,040

Rep: Reputation: 373Reputation: 373Reputation: 373Reputation: 373
I fail to see why that will not work.

You mean like in this case:

Code:
#!/bin/bash
# 1.sh

./2.sh "$@"

Code:
#!/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?

Last edited by i92guboj; 04-06-2009 at 05:48 PM.
 
Old 04-06-2009, 06:00 PM   #6
msreddy999
LQ Newbie
 
Registered: Apr 2004
Posts: 6

Original Poster
Rep: Reputation: 0
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

Hope that makes it clear
 
Old 04-06-2009, 06:17 PM   #7
i92guboj
Gentoo support team
 
Registered: May 2008
Location: Lucena, Cˇrdoba (Spain)
Distribution: Gentoo
Posts: 4,040

Rep: Reputation: 373Reputation: 373Reputation: 373Reputation: 373
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.
 
Old 04-06-2009, 08:37 PM   #8
msreddy999
LQ Newbie
 
Registered: Apr 2004
Posts: 6

Original Poster
Rep: Reputation: 0
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.
 
Old 04-07-2009, 03:55 AM   #9
i92guboj
Gentoo support team
 
Registered: May 2008
Location: Lucena, Cˇrdoba (Spain)
Distribution: Gentoo
Posts: 4,040

Rep: Reputation: 373Reputation: 373Reputation: 373Reputation: 373
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).
 
Old 04-07-2009, 04:24 PM   #10
msreddy999
LQ Newbie
 
Registered: Apr 2004
Posts: 6

Original Poster
Rep: Reputation: 0
Awesome. Thanks kenoshi and i92guboj. I think I finally got it. Thanks for detailed explanation.
 
Old 04-07-2009, 04:38 PM   #11
norobro
Member
 
Registered: Feb 2006
Distribution: Debian Sid
Posts: 241

Rep: Reputation: 45
I'm jumping in a little late, but here goes...

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
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
pass arguments and return values from a function in UNIX gaynut Programming 4 07-10-2008 01:56 AM
Looking for a more effecient way to pass arguments to functions. RHLinuxGUY Programming 10 05-01-2006 10:52 PM
How to pass structure as function arguments ssg14j Programming 2 08-20-2005 09:59 PM
How to pass arguments from $prompt for php script ukjairaj Linux - Software 4 06-25-2004 11:14 AM
How can we pass arguments to installpkg ? frenchi Slackware 3 04-23-2004 06:43 PM


All times are GMT -5. The time now is 11:43 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration