How to keep quotes in Bash arguments?

using "$@" will substitute the arguments as a list, without re-splitting them on whitespace (they were split once when the shell script was invoked), which is generally exactly what you want if you just want to re-pass the arguments to another program.

Note that this is a special form and is only recognized as such if it appears exactly this way. If you add anything else in the quotes the result will get combined into a single argument.

What are you trying to do and in what way is it not working?


There are two safe ways to do this:

1. Shell parameter expansion: ${variable@Q}:

When expanding a variable via ${variable@Q}:

The expansion is a string that is the value of parameter quoted in a format that can be reused as input.

Example:

$ expand-q() { for i; do echo ${i@Q}; done; }  # Same as for `i in "$@"`...
$ expand-q word "two words" 'new
> line' "single'quote" 'double"quote'
word
'two words'
$'new\nline'
'single'\''quote'
'double"quote'

2. printf %q "$quote-me"

printf supports quoting internally. The manual's entry for printf says:

%q Causes printf to output the corresponding argument in a format that can be reused as shell input.

Example:

$ cat test.sh 
#!/bin/bash
printf "%q\n" "$@"
$ 
$ ./test.sh this is "some test" 'new                                                                                                              
>line' "single'quote" 'double"quote'
this
is
some\ test
$'new\nline'
single\'quote
double\"quote
$

Note the 2nd way is a bit cleaner if displaying the quoted text to a human.

Related: For bash, POSIX sh and zsh: Quote string with single quotes rather than backslashes

Tags:

Quotes

Bash