7

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.

user242114
  • 101
  • 1
  • 1
  • 4
  • 2
    Possible duplicate of [What does dash "-" at the end of a command mean?](https://unix.stackexchange.com/questions/41828/what-does-dash-at-the-end-of-a-command-mean) – muru Feb 12 '18 at 04:24
  • @muru not a duplicate – roaima Feb 12 '18 at 15:42
  • @roaima why not? – muru Feb 12 '18 at 15:52
  • @muru your duplicate explains `-` as a marker to read from _stdin_. As you can see from [the (unfortunately downvoted) answer here](https://unix.stackexchange.com/a/423503/100397) the `-` can mean different things to different shells. For `bash` it's a synonym for `--` and not a _stdin_ marker. For at least one other shell it appears to be undefined. – roaima Feb 12 '18 at 17:08
  • @roaima "It's not a shell construct and it depends on the program you're using. Check the manpage if in doubt!" Without a clarification on what sh is here, that's the best possible answer. – muru Feb 13 '18 at 00:23
  • @muru sounds good to me. Why not propose that as an answer here? Either way, it's not anything like the answers offered on your suggested duplicate – roaima Feb 13 '18 at 08:36
  • @roaima uh... that is a quote from the first paragraph of the accepted answer on the dupe. – muru Feb 13 '18 at 08:37
  • @muru to my reading that snippet _in context_ qualifies the first part of that same paragraph that says `-` is a marker for _stdin_. I guess on this one we just disagree. – roaima Feb 13 '18 at 09:24
  • 1
    See also [Why the "-" in the "#! /bin/sh -" shebang?](//unix.stackexchange.com/q/351729) – Stéphane Chazelas Aug 17 '18 at 09:03

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](http://pubs.opengroup.org/onlinepubs/9699919799.2018edition/utilities/sh.html)). 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](http://zsh.sourceforge.net/Doc/Release/Invocation.html) *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