Handling of '--' in arguments of /bin/sh: POSIX vs implementations by Bash/Dash/FreeBSD's sh
The answer to the question "What does Posix prescribe" is already present in the OP. But the important feature of the Posix standard is not highlighted: the -c
option does not take an argument.
You can see this in the Synopsis:
sh -c [-abCefhimnuvx] [-o option]... [+abCefhimnuvx] [+o option]... command_string [command_name [argument...]]
What the -c
flag does is cause the positional parameters ("operands") to be interpreted in a different way. Without -c
, they are interpreted as [command_file [argument...]]
:
sh [-abCefhimnuvx] [-o option]... [+abCefhimnuvx] [+o option]... [command_file [argument...]]
That, by the way, is why sh -c+x
is an error. If -c
took an argument, then it would be legal to include the argument in the same word.
So, to answer the more specific questions:
Posix says "A single hyphen shall be treated as the first operand and then ignored...". Does that apply to a
-
immediately following-c
?A: Yes, it does.
-c
is a complete option, and the-
is therefore an operand. By contrast,-
in-o -
would not be treated as an operand. (It would be treated as an invalid option name.)Which one is right, Dash/Bash or FreeBSD?
A: In this case, Dash and Bash are Posix-compliant, and FreeBSD's sh is not. FreeBSD's shell considerably predates the current Posix specification, and I don't believe it ever purported to be fully compliant to any Posix specification.
How do I portably use
sh
to run a command whose name begins with a+
?A: I would think the following would work on any shell:
sh -c " +x"
" +x"
will not be recognized as an option because it doesn't start with a+
or-
, andsh -c
causes the operand to be parsed as a shell command, so leading whitespace will be ignored. I don't have a copy of FreeBSD'sash
to play with just now, so I welcome corrections.Or you could use a simple compound command:
sh -c "{ +x; }"
Possibly clearest (assuming the shell you're using implements the Posix-standard builtin
command
) is:sh -c "command +x"