Co oznacza „-” w „bash -”?

33

Co bash -oznacza poniższy kod powłoki bash? Wydaje się, że jest używany do pobrania ostatniego kodu jako danych wejściowych. Jeśli tak, czy mogę to po prostu napisać jako bashlub xargs bash?

curl --silent --location https://rpm.nodesource.com/setup | bash -
Searene
źródło

Odpowiedzi:

36

W razie wątpliwości przeczytaj kod źródłowy. =)

Bash 4.3, shell.cwiersz 830, w funkcjiparse_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);

Innymi słowy, oznacza -to, że nie ma już żadnych opcji . Jeśli w wierszu poleceń były jeszcze jakieś słowa, byłyby one traktowane jako nazwa pliku, nawet jeśli słowo zaczyna się od -.

W twoim przykładzie jest to oczywiście -całkowicie zbędne, ponieważ i tak nic za tym nie idzie. Innymi słowy, bash -jest dokładnie równoważne zbash .


Bash przyjmuje polecenia

  1. z pliku skryptu, jeśli jest podany w wierszu poleceń, lub
  2. nieinteraktywnie od swojego standardowego wejścia, jeśli standardowe wejście nie jest TTY (tak jak w twoim przykładzie: standardowe wejście jest potokiem, więc Bash wykona zawartość tego adresu URL jako skrypt), lub
  3. interaktywnie, jeśli jego standardem jest TTY.

Jest to nieporozumienie, które bash -każe Bashowi czytać polecenia ze standardowego wejścia. Chociaż prawdą jest, że w twoim przykładzie Bash będzie czytał swoje polecenia ze standardowego wejścia, zrobiłby to niezależnie od tego, czy -w wierszu poleceń był znak , ponieważ, jak wspomniano powyżej, bash -jest identyczny bash.

Aby dodatkowo zilustrować, że -to nie oznacza stdin, rozważ:

  • catKomenda jest przeznaczony interpretować -jako stdin. Na przykład:

    $ 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
  • W przeciwieństwie do tego, nie można dostać Bash wykonać /bin/datewtedy /bin/hostname, próbując w ten sposób:

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

    Próbuje raczej interpretować /bin/hostnamejako plik skryptu powłoki, co kończy się niepowodzeniem, ponieważ jest to garść binarnego gobbledygook.

  • Nie można wykonać date +%sprzy użyciu bash -żadnego z nich.

    $ 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

Czy możesz xargs bashzamiast tego pisać ? Nie. curl | xargs bashWywołałoby bash z zawartością skryptu jako argumenty wiersza poleceń. Pierwsze słowo treści byłoby pierwszym argumentem i prawdopodobnie zostałoby źle zinterpretowane jako nazwa skryptu.

200_sukces
źródło
6
głosuj na jedyną właściwą odpowiedź.
geirha
Rzeczywiście: według słów stronyAn argument of - is equivalent to --.
steeldriver
Jeśli naprawdę naprawdę chciałbyś użyć xargszamiast tego, działałoby (w ograniczonym scenariuszu wystarczająco małego skryptu wejściowego) z | xargs bash -c; ale tak naprawdę nie jest to użyteczne ani idiomatyczne zastosowanie xargs.
tripleee
@tripleee Jeśli zawartość adresu URL jest czymś więcej niż linią jednowierszową, wówczas linie są przerywane i inne separatory prawdopodobnie byłyby błędne.
200_success
Oczywiście masz rację.
tripleee