プログラムが標準入力から読み取らず、ファイルからのみ読み取る場合は、/dev/stdinを使用しても安全ですか?

プログラムが標準入力から読み取らず、ファイルからのみ読み取る場合は、/dev/stdinを使用しても安全ですか?

プログラムAの出力をプログラムBにパイプしたいです。プログラムBはstdinでの読み取りをサポートせず、ファイルからの読み取りのみをサポートします。単にA | dev / stdinを実行できますか?

実際に動作しているように見えますが、パイプを実行するときにBが/ dev / stdinから取得する唯一のものはAが書いたものであることを確認したいと思います。

答え1

ここ

A | B /dev/stdin

Bのstdinはパイプなので、/dev/stdin名前付きパイプのように動作します。

Bしたがって、次の代わりにファイルを一度開き、最初から順番にコンテンツを読み取る場合にのみ機能します。

  • フォーマットを事前に確認して、通常のファイルであることを確認します(ファイルはLinuxではNamed Pipe、LinuxではNamed Pipeと表示されます)。キャラクターデバイス他のほとんどのシステムでは)。
  • あらかじめサイズを確認して
  • 何度も開きます。
  • ファイルで検索する必要があります(カーソルの位置を変更する)(巻き戻し、終了に移動...)
  • mmap()通常のファイルでは機能しますがパイプでは機能しない他の作業が必要です。

もちろん、B標準入力では読めません。たとえば、次のように別のファイル記述子を使用します。プロセスの交換( B <(A)ksh/zsh/bash で) はこの問題を回避できます。これはまた、Bすべてのファイル記述子がランダムに閉じられてはならないことを意味します(sudo上記のfds 2に対して実行するようないくつかのコマンドのように)。

ほとんどのコマンドは単にファイルを最初から最後まで順番に読み込みますが、一部のコマンドはただ標準入力で入力を実行するのではなく、ファイル名引数で入力を実行するのは実際に上記の理由で実行できないため、マイルが異なる場合があります。

$ unzip -l file.zip
Archive:  file.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
    48894  2020-12-05 07:35   file
---------                     -------
    48894                     1 file
$ cat file.zip | unzip -l /dev/stdin
Archive:  /dev/stdin
  End-of-central-directory signature not found.  Either this file is not
  a zipfile, or it constitutes one disk of a multi-part archive.  In the
  latter case the central directory and zipfile comment will be found on
  the last disk(s) of this archive.
unzip:  cannot find zipfile directory in one of /dev/stdin or
        /dev/stdin.zip, and cannot find /dev/stdin.ZIP, period.

infozip ファイルは順次処理できないファイルであり、ファイルの実際のデータにアクセスするには、まずファイルの末尾にあるインデックスを読み取る必要があります。

1極端なケースでは、Linuxのksh93シェルはパイプの代わりにソケットペアを使用することに注意してください。垣間見る)。 Linuxでは、/dev/stdin他のシステムなどの特殊文字デバイスではないため「魔法」物理ファイルへのシンボリックリンク。/dev/stdinこの場合、開くことができないため動作しません。開いているアウトレット。

$ ksh93 -c 'echo test | cat /dev/stdin'
cat: /dev/stdin: No such device or address

ksh93では、システムに関係なくパイプを使用するプロセスオーバーライドを使用する必要があります。

$ ksh93 -c 'cat <(echo test)'
test

答え2

(JdeBPのコメントもご覧ください)

はい、しかし推奨される方法はを使用することです/dev/fd/0。たとえば、本に記載されています。「UNIX環境の高度なプログラミング」:

これにより、パス名引数を使用するプログラムが他のパス名と同じ方法で標準入力と標準出力を処理できるようになります。

/dev/fd/0そして/dev/stdin同じデバイスです。役に立つ情報については、こちらをご覧ください。

関連情報