2

I have been searching for half an hour in vain!

This looks simple enough:

#!/bin/bash
#test.sh
echo "$0 $@">>my.log

Run command:

test.sh -a -b 'abc -c 123'
test.sh -a -b "abc -c 123"

Output:

cat my.log
test.sh -a -b abc -c 123
test.sh -a -b abc -c 123

Expected output:

cat my.log
test.sh -a -b 'abc -c 123' 
test.sh -a -b "abc -c 123"

Notice the single quote in the expected output.

How do I get the expected output, do I have to manually put the quotes in?

The intention is that: I want to keep a log of how a script is invoked for later tracing back how I did my work. So the log lines must keep PRECISELY how the command was invoked and I can copy-paste and run it again.

After many searches and trials, all tricks with quotes escaping, and printf don't work. Like Others mentioned, this seems to be an built-in behavior of Bash in parse arguments that it strip off quotes. I am just wondering if it is somehow possible to pick the line from bash history, which records precisely how commands are invoked.

biocyberman
  • 5,675
  • 8
  • 38
  • 50
  • 1
    In the way you're calling, you can't. See also [Preserving quotes in bash function parameters](http://stackoverflow.com/questions/3260920/preserving-quotes-in-bash-function-parameters). – bishop Feb 25 '15 at 15:17

5 Answers5

1

Just quote the parameters you send:

$ ./a "-a -b 'abc -c 123'"
$ ./a '-a -b "abc -c 123"'

And the output is...

$ cat my.log 
./a -a -b 'abc -c 123'
./a -a -b "abc -c 123"
fedorqui
  • 275,237
  • 103
  • 548
  • 598
  • This is not what I am looking for. The log lines do not record PRECISELY how the commands were invoked. – biocyberman Feb 25 '15 at 15:20
  • 1
    Then update your question to reflect more clearly what are you looking for. – fedorqui Feb 25 '15 at 15:23
  • @biocyberman in fact I think *this* is the answer: " The reason this happens is because bash interprets the arguments, as you thought. The quotes simply aren't there any more when it calls the function, so this isn't possible. It worked in DOS because programs could interpret the command line themselves, not that it helps you!" from http://stackoverflow.com/a/3260940/1983854 – fedorqui Feb 25 '15 at 15:39
1

This won't get you the exact (quote-for-quote) output to match your input but I believe it does get you functionally identical output.

$ cat test.sh
#!/bin/bash
printf -- '%q' "$0"; printf -- ' %q' "$@"; echo
$ ./test.sh -a -b 'abc -c 123'
./test.sh -a -b abc\ -c\ 123
$ ./test.sh '-a 555' "-b 6 7 8" abc\ -c\ 123
./test.sh -a\ 555 -b\ 6\ 7\ 8 abc\ -c\ 123

I believe this is the closest you can get to what you want. The original quotes (or escapes) are gone by the time your script sees the arguments. It cannot reproduce them exactly.

Etan Reisner
  • 77,877
  • 8
  • 106
  • 148
0

If you want the quotes in the script you can also escape the quotes using a backslash.

test.sh -a -b \'abc -c 123\'
test.sh -a -b \"abc -c 123\"
Asheliahut
  • 901
  • 6
  • 11
0

Iterate over them:

#!/bin/bash
echo -n "$0 "
for arg in "$@"; do echo -n "'$arg' "; done
echo

This'll get you:

./test.sh '-a' '-b' 'abc -c 123'
for
./test.sh -a -b 'abc -c 123'

This is simple, but doesn't handle arguments with single quotes inside of them (such as "don't"), thought, but it does handle those spaces, including spaces inside of your executable's name.

You can't get the original quotation mark. They don't get send to the target script. That information is last during the invocation. What gets sent is the bash-interpreted arguments (after globs and escape sequences are expanded). Quoting you have to do yourself -- single quotes handle most common cases.

Petr Skocik
  • 58,047
  • 6
  • 95
  • 142
0

Don't know other way except this:

test.sh -a -b \'abc -c 123\'
test.sh -a -b \"abc -c 123\"
candymanuu
  • 110
  • 7