Verwendung des Bindestrichs (-) anstelle eines Dateinamens

110

Wenn für einen Befehl -anstelle eines Dateinamens ein Argument verwendet wird, bedeutet dies STDIN oder STDOUT.

  1. In diesem Beispiel wird jedoch eine Datei mit dem Namen erstellt -:

    echo hello > -

    Wie kann ich -in diesem Beispiel STDOUT bedeuten?

  2. Umgekehrt, wie kann ich -eine Datei mit folgenden Namen bedeuten -:

    cat -
Tim
quelle
3
Da ich anscheinend 50 Ruf haben muss, um direkt zu kommentieren ... Auf dem / dev / stdin / dev / stdout-Kommentar hat AIX, das ein legitimes UNIX-Derivat ist, diese Pseudo-Geräte nicht. Und LINUX ist in keinem Fall ein UNIX-Derivat. Es ist ein POSIX-kompatibles Betriebssystem und derzeit das beliebteste unter den UNIX-Betriebssystemen, aber machen Sie keinen Fehler, dies ist kein UNIX. Aber der Kern der Antworten hier ist richtig. Die "-" Notation wird von der Shell nicht als speziell interpretiert und somit als ARG direkt an jede einzelne Anwendung übergeben. Wenn die Anwendung nicht erkennt
Es gibt auch 2>&-Konstruktionen, die "Nahdeskriptor 2" bedeuten.
user3132194
@ user95873, ich nehme an, Sie wollten sagen: Während Linux Unix-artig ist, ist nicht jedes Unix-artige (oder echte UNIX) Linux . Die Frage, ob Linux wahr ist oder nicht, hat keinen Bezug zum / dev / std {in, out, err} -Problem. Als / dev / std {in, out, err} wurde ein Feature hinzugefügt , das nicht fehlt .
Sasha

Antworten:

156

Unter Verwendung -als Dateinamen stdin / stdout zu verstehen ist eine Konvention , die viele Programme verwenden. Es ist keine spezielle Eigenschaft des Dateinamens. Der Kernel erkennt dies nicht -als besonders. Daher werden Systemaufrufe, die auf -einen Dateinamen verweisen, -buchstäblich als Dateinamen verwendet.

-Wird bei der Bash-Umleitung nicht als besonderer Dateiname erkannt, verwendet Bash diesen als wörtlichen Dateinamen.

Wenn catdie Zeichenfolge -als Dateiname angezeigt wird, wird sie als Synonym für stdin behandelt. Um dies zu umgehen, müssen Sie den angezeigten String so ändern cat, dass er immer noch auf eine aufgerufene Datei verweist -. Die übliche Vorgehensweise besteht darin, dem Dateinamen den Pfad - ./-, oder - voranzustellen /home/Tim/-. Diese Technik wird auch verwendet, um ähnliche Probleme zu umgehen, bei denen Befehlszeilenoptionen mit Dateinamen kollidieren, sodass beispielsweise eine Datei, auf die Bezug genommen wird, ./-enicht als -eBefehlszeilenoption für ein Programm angezeigt wird.

camh
quelle
37
Es ist hinzuzufügen , dass /dev/stdinund /dev/stdoutsind universell verfügbar und kann anstelle der verwendet werden -Konvention.
22.
Auch in diesem catFall kann die Verwendung der Umleitung anstelle der Auflistung des Arguments hilfreich sein cat <-:; Es wäre jedoch schwierig, dies zu mischen und abzugleichen, wenn mehrere Dateien gleichzeitig verkettet würden.
jmtd
10
@jmtd: / dev / std {in, out} sind nicht allgemein verfügbar. Nicht alle Unixe haben es.
22.07.11
2
Interessant, ich nahm an, dass sie Teil von POSIX waren (kann aber nicht bestätigen). Sie sind zumindest unter Linux, den BSDs und Solaris vorhanden. Können Sie ein Beispiel für ein modernes UNIX geben, dem es an ihnen mangelt?
2.
1
@camh Ich bin nicht sicher, ob Sie die Benachrichtigung erhalten haben, und dies ist ein sehr, sehr altes Thema. Ich bin nicht sicher, ob Sie können, aber ich bin sehr neugierig, ob Sie die Antwort auf jmtddie Frage wissen ? :)
Swivel
18
  1. Stattdessen echo hello > -können Sie verwenden echo hello > /dev/stdout.

    Während '-' eine Konvention ist, die von jedem Programm implementiert werden muss, das sie unterstützen möchte /dev/stdin, /dev/stdoutund /dev/stderrwenn sie vom Betriebssystem unterstützt wird (zumindest von Solaris, Linux und BSDs), unabhängig von der Anwendung ist und dann wie Sie funktioniert wollen.

jlliagre
quelle
9

Wie bereits erwähnt , -ist dies nur eine Namenskonvention, die von einigen Programmen verwendet wird. Wenn Sie auf diese Streams mit einem Dateideskriptor verweisen möchten, den die Shell erkennt, war es richtig, dass Sie den Namen /dev/stdinoder /dev/stdoutstattdessen verwendet haben. Diese Dateinamen sollten an jedem Ort funktionieren, an dem ein normaler Dateiname funktionieren würde.

  1. Davon abgesehen ist Ihr erstes Beispiel irgendwie albern. Alle Ausgaben, die vom Redirect-Operator zum Schreiben in eine Datei abgefangen werden, sind bereits auf ON-Standardausgabe gesetzt. Das Umleiten und Zurückschreiben an den Speicherort ist daher sinnlos. Das Verhalten, das Sie dort verwenden, ist die Pipe, keine Umleitung:

    echo hello |
  2. In Ihrem zweiten Beispiel müssen Sie lediglich angeben, dass Sie eine Wurfdatei mit diesem Namen und nicht mit dem internen Aliasnamen möchten. Sie können dies am einfachsten tun, indem Sie einen Pfad zu der Datei wie folgt angeben:

    cat ./-
Caleb
quelle
6

Wie bei 1 muss das Programm dies unterstützen. Sie können es nicht einfach beliebig verwenden. Wie für 2, leiten Sie die Eingabe von (z cat < -. B. ) um.

Bahamat
quelle
1

Der '-' Ansatz hat viele Probleme. Erstens erfordert es eine Interpretation des '-' Zeichens und viele Programme führen eine solche Interpretation nicht durch. Darüber hinaus gibt es einige Programme, die einen Bindestrich als Trennzeichen für das Ende der Befehlszeilenoptionen interpretieren. Die Programme sind so geschrieben, dass sie mit Dateinamenargumenten arbeiten. Der '-' Ansatz ist ein Hack, nett, aber schwach.

Der beste Weg ist:

$ echo hello > /dev/fd/1

/dev/stdout ist ein symbolischer Link von /dev/fd/1

b3h3m0th
quelle
Die Umleitung wird von der Shell interpretiert, nicht vom aufgerufenen Programm.
Sherrellbc