newspaint

Documenting Problems That Were Difficult To Find The Answer To

Passing Variable Number of Command Line Arguments in BASH

The Problem

Sometimes you want to write a script that calls another program but passes all the command-line arguments to that other program. The problem is that the arguments might contain space that you would ordinary enclose in quote marks.

For example, imagine if you wanted to write a script that put a vertical line between the arguments. You might do this as follows:

me@host:~# perl -e "print( join('|',@ARGV) )" one "four hundred" twelve
one|four hundred|twelve

Now you want to wrap this in a shell script so that you don’t have to remember the Perl code:

#/bin/bash

perl -e "print( join('|',@ARGV) )" $@

But this doesn’t work because if you try running this you’ll get the following:

me@host:~# myscript.sh one "four hundred" twelve
one|four|hundred|twelve

Clearly this is a problem. There should have been a space between “four” and “hundred”.

The Solution

The trick is to use the expression ${1+"$@"} as this wraps quote marks around each argument if there is at least one argument.

So if we change the script to the following:

#/bin/bash

perl -e "print( join('|',@ARGV) )" ${1+"$@"}

.. then the script will work as expected now:

me@host:~# myscript.sh one "four hundred" twelve
one|four hundred|twelve

How Does This Work?

Any expression ${variable+alternative} will result in alternative if variable isn’t set. The expression "$@" expands to each parameter with double quotes around it if there is at least one parameter. The problem is that "$@" results in a single zero-length parameter if there are no arguments. And sometimes you need to pass no parameters to a command.

so instead of passing "$@" to the command, we test to see if the first argument exists, ${1+alternative} and provide "$@" if it does (i.e. ${1+"$@"}).

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: