What does the last "-" (hyphen) mean in options of `bash`?
In this tutorial we need to execute the following command:
# curl -sL | sudo -E bash -What does the last - (hyphen) after bash mean?
I've seen a lot of commands with this, and couldn't find myself a logical explanation and neither find how to reformulate a google search for it. Is it the output of the piped command?
43 Answers
Bash behaves in somewhat non-standard way when it comes to -.
POSIX says:
Guideline 10:
The first--argument that is not an option-argument should be accepted as a delimiter indicating the end of options. Any following arguments should be treated as operands, even if they begin with the-character.[…]
Guideline 13:
For utilities that use operands to represent files to be opened for either reading or writing, the-operand should be used to mean only standard input (or standard output when it is clear from context that an output file is being specified) or a file named-.
And
Where a utility described in the Shell and Utilities volume of POSIX.1-2017 as conforming to these guidelines is required to accept, or not to accept, the operand
-to mean standard input or output, this usage is explained in the OPERANDS section. Otherwise, if such a utility uses operands to represent files, it is implementation-defined whether the operand-stands for standard input (or standard output), or for a file named-.
But then man 1 bash reads:
A
--signals the end of options and disables further option processing. Any arguments after the--are treated as filenames and arguments. An argument of-is equivalent to--.
So for Bash - means neither standard input nor a file, hence somewhat non-standard.
Now your particular case:
curl -sL | sudo -E bash -
I suspect the author of this command may not realize - is equivalent to -- in this case. I suspect the author wanted to make sure bash will read from its standard input, they expected - to work according to the guideline 13.
But even if it worked according to the guideline, - would be unnecessary here because bash detects when its standard input is a pipe and acts accordingly (unless -c is given etc.).
Yet - doesn't work according to the guideline, it works like --. Still -- is unnecessary here because there are no arguments after it.
In my opinion the last - changes nothing. The command would work without it.
To see how -- and - can be useful in general, study the example below.
cat in my Kubuntu obeys both guidelines and I will use it to demonstrate usefulness of - and --.
Let a file named foo exist. This will print the file:
cat fooLet a file named --help exist. This won't print the file:
cat --helpBut this will print the file named --help:
cat -- --helpThis will concatenate the file named --help with whatever comes from the standard input:
cat -- --help -It seems you don't really need --, because you can always pass ./--help which will be interpreted as a file for sure. But consider
cat "$file"when you don't know beforehand what the content of the variable is. You cannot just prepend ./ to it, because it may be an absolute path and ./ would break it. On the other hand it may be a file named --help (because why not?). In this case -- is very useful; this is a lot more robust command:
cat -- "$file" 0 In man bash, at the end of the single-character options there is:-
-- A -- signals the end of options and disables further option processing. Any arguments after the -- are treated as filenames and arguments. An argument of - is equivalent to --.If you have quoted the complete command, I can see no reason to use - after bash in this instance, but it does no harm.
curl -sL | sudo -E bash -bash - means that bash is waiting for stdin. So practically bash will execute whatever is returned by the command that is on the left of |
A similar but easier example would be:
echo hello | cat -here, cat will print 'hello'. Why? Because 'hello' is being sent to cat through | and cat is waiting for anything sent to it
Now let's break the entire command into two:
curl -sL this curl command will return something that can be understood and executed by bash
then we have a pipe | which will send the output returned by curl command to to the right side of pipe i.e. sudo -E bash -. Finally in sudo -E bash -, bash is ready to execute anything that is sent to it