0

I am trying to write a Bash script that appends a string to a Bash array, where the string contains the path to a Python script together with the arguments passed into the Bash script, enclosed in double quotes.

If I call the script using ./script.sh -o "a b", I would like a CMD_COUNT of 1, but I am getting 2 instead.

script.sh:

#!/bin/bash

declare -a COMMANDS=()
COMMANDS+=("/path/to/myscript.py \"${@}\"")
CMD_COUNT=${#COMMANDS[*]}
echo $CMD_COUNT

How can I ensure that the appended string is /path/to/myscript.py "-o" "a b"?

EDIT: The full script is actually like this:

script.sh:

#!/bin/bash

declare -a COMMANDS=()
COMMANDS+=("/path/to/myscript2.py")
COMMANDS+=("/path/to/myscript.py \"${@}\"")
CMD_COUNT=${#COMMANDS[*]}
echo $CMD_COUNT

for i in ${!COMMANDS[*]}
do
    echo "${0} - command: ${COMMANDS[${i}]}"
    ${COMMANDS[${i}]}
done
3
  • 1
    Why would you want a single string /path/to/myscript.py "-o" "a b", and not an array with three strings, /path/to/myscript.py, -o, and a b? That array is in exactly the state you need to use it as a command line to invoke your program. The array with only one string... not so much. Commented Nov 3, 2020 at 17:34
  • BashFAQ #50 might be a place to start reading for background on why argument lists should be handled as arrays rather than strings containing literal quotes/whitespace/etc. Commented Nov 3, 2020 at 17:35
  • (BTW, all-caps variable names are used for variables that change or reflect behavior of the shell itself and other POSIX-standardized tools, whereas POSIX reserves variables with at least one lower-case character for application use -- see pubs.opengroup.org/onlinepubs/9699919799/basedefs/…, keeping in mind that shell variables and environment variables share a single namespace, so conventions necessarily apply to both). Commented Nov 3, 2020 at 17:36

1 Answer 1

1

It's a bad idea, but if it's what you really want, printf %q can be used to generate a string that, when parsed by the shell, will result in a given list of arguments. (The exact escaping might not be identical to what you'd write by hand, but the effect of evaluating it -- using eval -- will be).

#!/bin/bash

declare -a COMMANDS=( )

printf -v command '%q ' "/path/to/myscript" "$@"
COMMANDS+=( "$command" )
CMD_COUNT=${#COMMANDS[@]}
echo "$CMD_COUNT"

...but, as I said, this is all a bad idea.

Sign up to request clarification or add additional context in comments.

9 Comments

The appended string is /path/to/myscript.py -o a\ b, not what I wanted...
When you evaluate /path/to/myscript.py -o a\ b as source code in a shell, it has exactly the same behavior as /path/to/myscript.py -o "a b". As in, myscript.py can't distinguish between the two uses, because they both create the same sys.argv list.
@mck, ...since you're coming from a Python background: the above is like complaining that repr("""some string""") gives you 'some string' as output instead of spitting out """some string""" with the original triple-quotes. They're written different ways, but they're the exact same value.
Sorry @CharlesDuffy, I understand what you mean. It seems it's the script that I'm having is causing some trouble with backslash escapes. I'll edit my question to reflect that.
I have edited my question. The script doesn't work in the sense that it now got "a\" as the argument for "-o", rather than "a b". Using set -x shows that the script is called as /path/to/myscript.py -o 'a\' b
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.