Save quotes in bash arguments

I am creating a bash script that will print and pass complex arguments to another external program.

./script -m root@hostname,root@hostname -o -q -- 'uptime ; uname -a' 

How to print raw arguments as such:

 -m root@hostname,root@hostname -o -q -- 'uptime ; uname -a' 

Using $@ and $* removes single quotes around uptime ; uname -a uptime ; uname -a , which may cause unwanted results. My script does not need to parse every argument. I just need to print / write the line of the argument and pass them to another program, exactly as they are indicated.

I know that I can avoid quotes with something like "'uptime ; uname -a'" , but I cannot guarantee that the user will do this.

+15
linux bash
May 31 '12 at 14:48
source share
3 answers

The quotes are removed before the arguments are passed to your script, so it's too late to save them. What you can do is to preserve their effect when passing arguments to the internal command and restore the equivalent quoted / escaped version of the arguments for printing. A.

To pass arguments to the internal command "$@" - with double quotes, $ @ saves the original word breaks, which means that the internal command receives exactly the same list of arguments as your script.

For printing, you can use the% q format in the bash printf command to restore citation. Please note that this will not always lead to the restoration of the original quotation, but will build an equivalent quote / escaped string. For example, if you passed the argument 'uptime ; uname -a' 'uptime ; uname -a' , it can print uptime\ \;\ uname\ -a or "uptime ; uname -a" or any other equivalent (see @William Pursell's answer for similar examples).

Here is an example of their use:

 printf "Running command:" printf " %q" innercmd "$@" # note the space before %q -- this inserts spaces between arguments printf "\n" innercmd "$@" 
+13
May 31 '12 at 15:05
source share

If you want to print a list of arguments as close as possible to what the user may have entered:

 #!/bin/bash chars='[ !"#$&()*,;<>?\^`{|}]' for arg do if [[ $arg == *\'* ]] then arg=\""$arg"\" elif [[ $arg == *$chars* ]] then arg="'$arg'" fi allargs+=("$arg") # ${allargs[@]} is to be used only for printing done printf '%s\n' "${allargs[*]}" 

This is not perfect. An argument of type ''\''"' more complex to place than justified.

+4
May 31 '12 at 16:02
source share

If the user calls your command as:

 ./script 'foo' 

the first argument specified in the script is the string foo without quotes. It is impossible to distinguish your script from this and any other method by which it could receive foo as an argument (for example, ./script $(echo foo) or ./script foo or ./script "foo" or ./script \f\o""''""o )).

+3
May 31 '12 at
source share



All Articles