Was bedeutet das "-" in "bash -"?

33

Was bash -bedeutet der folgende Bash-Shell-Code? Es scheint verwendet zu werden, um die Ausgabe des letzten Codes als Eingabe zu übernehmen. Wenn ja, kann ich es einfach als bashoder schreiben xargs bash?

curl --silent --location https://rpm.nodesource.com/setup | bash -
Searene
quelle

Antworten:

36

Lesen Sie im Zweifelsfall den Quellcode. =)

Bash 4.3, shell.cZeile 830, in Funktionparse_shell_options() :

  /* A single `-' signals the end of options.  From the 4.3 BSD sh.
     An option `--' means the same thing; this is the standard
     getopt(3) meaning. */
  if (arg_string[0] == '-' &&
       (arg_string[1] == '\0' ||
         (arg_string[1] == '-' && arg_string[2] == '\0')))
    return (next_arg);

Mit anderen Worten heißt das -, dass es keine Optionen mehr gibt . Wenn sich in der Befehlszeile weitere Wörter befinden, werden diese als Dateiname behandelt, auch wenn das Wort mit a beginnt -.

In Ihrem Beispiel ist das natürlich -völlig überflüssig, da ohnehin nichts folgt. Mit anderen Worten bash -ist genau gleichbedeutend mitbash .


Bash nimmt seine Befehle entgegen

  1. aus einer Skriptdatei, wenn diese in der Befehlszeile angegeben ist, oder
  2. nicht interaktiv von seinem stdin, wenn sein stdin kein TTY ist (wie in Ihrem Beispiel: stdin ist eine Pipe, so dass Bash den Inhalt dieser URL als Skript ausführt), oder
  3. interaktiv, wenn sein stdin ein TTY ist.

Es ist ein Missverständnis, bash -das Bash anweist, seine Befehle von seiner Standardeingabe zu lesen. Während es ist wahr , dass in Ihrem Beispiel Bash seine Befehle von stdin gelesen wird, wäre es so , unabhängig davon geschehen , ob es eine war -auf der Kommandozeile, da, wie oben erwähnt, bash -zu identisch ist bash.

Um weiter zu veranschaulichen, dass -das nicht stdin bedeutet, betrachten Sie:

  • Der catBefehl ist so konzipiert, dass er ein -als stdin interpretiert . Beispielsweise:

    $ echo xxx | cat /etc/hosts - /etc/shells
    127.0.0.1 localhost
    xxx
    # /etc/shells: valid login shells
    /bin/sh
    /bin/dash
    /bin/bash
    /bin/rbash
    /bin/zsh
    /usr/bin/zsh
    /usr/bin/screen
    /bin/tcsh
    /usr/bin/tcsh
    /usr/bin/tmux
    /bin/ksh93
  • Im Gegensatz dazu können Sie nicht Bash erhalten auszuführen /bin/datedann /bin/hostnamedurch diese versuchen:

    $ echo date | bash - hostname
    /bin/hostname: /bin/hostname: cannot execute binary file

    Vielmehr wird versucht, die /bin/hostnameDatei als Shell-Skript zu interpretieren , was fehlschlägt, da es sich um eine Menge Binär-Gobbledy-Gook handelt.

  • Sie können nicht ausgeführt werden date +%sunter Verwendung von bash -entweder.

    $ date +%s
    1448696965
    $ echo date | bash -
    Sat Nov 28 07:49:31 UTC 2015
    $ echo date | bash - +%s
    bash: +%s: No such file or directory

Kannst du xargs bashstattdessen schreiben No. curl | xargs bashwürde bash mit dem Inhalt des Skripts als Befehlszeilenargumente aufrufen. Das erste Wort des Inhalts wäre das erste Argument und würde wahrscheinlich als Skriptdateiname falsch interpretiert.

200_erfolg
quelle
6
upvote für die einzig richtige antwort.
Geirha
In der Tat: In den Worten der ManpageAn argument of - is equivalent to --.
steeldriver 28.11.15
Wenn Sie wirklich, wirklich xargsstattdessen verwenden wollten , würde es funktionieren (im begrenzten Szenario eines ausreichend kleinen Eingabeskripts) mit | xargs bash -c; Aber in Wirklichkeit ist dies keine sinnvolle oder idiomatische Verwendung von xargs.
Tripleee
@tripleee Wenn der Inhalt der URL mehr als ein Einzeiler ist, dann sind die Zeilenumbrüche und andere Begrenzer wahrscheinlich alle falsch.
200_erfolg
Du hast natürlich recht.
Tripleee