This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author nik-sm
Recipients jweese, nik-sm
Date 2020-02-20.18:35:47
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1582223747.93.0.587274684946.issue39692@roundup.psfhosted.org>
In-reply-to
Content
Good point - the phrasing I suggested there is not accurate, and there is more complicated behavior available than simply specifying a single executable. Here's the bash manual's info about "-c" flag:

"""
If the -c option is present, then commands are read from the first non-option argument command_string.   If  there  are arguments  after  the  command_string, the first argument is assigned to $0 and any remaining arguments are assigned to the positional parameters.  The assignment to $0 sets the name of the shell, which is used in warning  and  error  messages.
"""

So the command_string provided (the first word or the first quoted expression) is interpreted as a shell program, and this program is invoked with the remaining words as its arguments. As you point out, this command_string can be a terminal expression like `true`, a function definition like you provided, an executable, or other possibilities, but in any case it will be executed with the remaining args.

(This also matches how the library code assigns `executable`: https://github.com/python/cpython/blob/master/Lib/subprocess.py#L1707)

As you say, simply slapping quotes around all the args produces a subtle difference: the arg in the position of `$0` is used as an actual positional parameter in one case, and as the shell name in the other case:

$ bash -c 'f() { printf "%s\n" "$@"; }; f "$@"' - foo bar baz
foo
bar
baz
 $ bash -c 'f() { printf "%s\n" "$@"; }; f "$@" - foo bar baz'
-
foo
bar
baz

(Unless I am misunderstanding the behavior here).

It's a bit frustrating that this approach would not work to simplify the usage, but (assuming my explanation is correct) I concede that code might certainly be depending on this behavior and setting the shell name with args[1] (and they would not want this to become a positional parameter instead).


Improving on my first attempt, here's another possible phrasing for the docs:
"""
Using `shell=True` invokes the sequence of args via `<SHELL> -c` where <SHELL> is the chosen system shell (described elsewhere on this page). In this case, the item at args[0] is a shell program, that will be invoked on the subsequent args. The item at args[1] will be stored in the shell variable `$0`, and used as the name of the shell. The subsequent items at args[2:] will be stored as shell parameters (`$1`, `$2`, etc) and available as positional parameters (e.g. using `echo $@`).
"""

I would certainly be happy to defer on giving a precise and thorough statement for the docs, but clarifying/highlighting this behavior definitely seems useful.

Thanks again
History
Date User Action Args
2020-02-20 18:35:47nik-smsetrecipients: + nik-sm, jweese
2020-02-20 18:35:47nik-smsetmessageid: <1582223747.93.0.587274684946.issue39692@roundup.psfhosted.org>
2020-02-20 18:35:47nik-smlinkissue39692 messages
2020-02-20 18:35:47nik-smcreate