8

I know that sh just calls the default shell, so "bash -" means the same. But can someone explain the syntax to me. I tried looking in the bash manual, but couldn't find it. I came across this because I wanted to execute the output of a command. Ex.

echo date | sh -

prints out the date.

1 Answers1

6

Yes, sh - and bash - do mean the same.

In man bash, there is this description (emphasis mine):

--
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 --

That simply means that it signals the end of options and that any following tokens are arguments (not options) even if they start with a dash -.

And a POSIX sh has a similar description.

Thus, this volume of POSIX.1-2017 allows the single to mark the end of the options, in addition to the use of the regular "--" argument, because it was considered that the older practice was so pervasive.

This command:

$ echo "date" | sh -
Mon Feb 12 00:00:00 UTC 2018

But also does this:

$ echo "date" | sh
Mon Feb 12 00:00:00 UTC 2018

And this

$ echo "date" | sh -s
Mon Feb 12 00:00:00 UTC 2018

This will make clear what is being executed:

$ echo "date" | sh -x 
+ date
Mon Feb 12 00:00:00 UTC 2018

But this will fail:

$ echo "date" | sh - -x
sh: 0: Can't open -x

That means that the date string is being read as a command from the standard input and that the dash (-) signals the end of options and start the arguments (the same as -- would do).

  • Date | sh - wouldn’t work. echo date | sh - would though. Ok, so now we know what - does. It’s actually unnecessary. Can you do the same with xargs. I’m on a mac, so it’s BSD version of xargs. I tried echo date | xargs, but it didn’t work. – user242114 Feb 12 '18 at 03:55
  • Even on the Mac, echo date|xargs should print the word date to stdout. Of course in this case, you could simply write echo date, but redundantly piping it to xargs still should not cause any problem. What error message do you get? – user1934428 Feb 12 '18 at 07:28
  • I was trying to execute date. I could write “ echo date | xargs xargs, but that doesn’t work in the mac version of xargs. So eval doesn’t accept piped input, source has a bug in bash 3.2 (mac version) and you can’t do xargs xargs on the mac. This leaves us with using a while loop “while read line; do $line; done” – user242114 Feb 12 '18 at 13:56
  • The dash/hyphen is a standard option (or whatever it should be called) for POSIX sh (link). The way to force the shell to read from stdin is -s, e.g. echo 'echo "args: $*"' | bash -s - foo bar prints args: foo bar. – ilkkachu Aug 17 '18 at 08:54
  • @ilkkachu In the link you provide what it says is: allows the single to mark the end of the options, in addition to the use of the regular "--" argument and also, as a probably less easy to understand description: - A single shall be treated as the first operand and then ignored. understand the "first option" as something after the last option. So, it (the single dash) should be understood to be the "end of options" in both cases. –  Aug 17 '18 at 10:13
  • @ilkkachu Also note that your command works exactly the same as this: echo 'echo args: $*' | bash -s foo bar (with no dash). That is, the dash is ignored. –  Aug 17 '18 at 10:16
  • Compare echo 'echo args: $*' | bash -s -x foo bar with echo 'echo args: $*' | bash -s - -x foo bar. @ilkkachu –  Aug 17 '18 at 10:45
  • @Isaac, yeah, I played around with the dash and -s and forgot it there, it's not needed in that command. My point was mostly that - is standard in the meaning you quoted from Bash's manual. -s is needed if there are arguments (unless you use /dev/stdin or something like that instead) – ilkkachu Aug 17 '18 at 11:05
  • Actually, the POSIX page say: The standard input shall be used only if one of the following is true: (1) The -s option is specified. (2) The -c option is not specified and no operands are specified. So, if there are no operands (like in plain sh) the commands could be read from stdin. –  Aug 17 '18 at 11:11
  • Well, for zsh, it is documented as Firstly, a lone ‘-’ (or ‘+’) as an argument by itself ends option processing. @StéphaneChazelas –  Aug 17 '18 at 11:32
  • Oh yes, I missed that. – Stéphane Chazelas Aug 17 '18 at 12:17
  • What is meant by "An argument of - is equivalent to --" ? Do they mean that, after a --, if any - occurs, it will treated as -- ? – sofs1 Aug 10 '19 at 09:00
  • 1
    @sofs1 It means that a (first only) - is equivalent to a (first only) --. Any further - or -- are treated as normal arguments not having special meaning. Well, actually, naming files for the shell. –  Aug 10 '19 at 19:40