プロセス置換により、パイプである/ dev / fd / 63というファイルが作成されるのはなぜですか?


40

この特定の例のコンテキストで名前付きパイプを理解しようとしています。

私が入力し<(ls -l)、私の端末にとのような出力を得ますbash: /dev/fd/63: Permission denied

と入力するcat <(ls -l)と、ディレクトリの内容が表示されます。私が交換した場合catecho、私は端末名を取得すると思います(またはそれを何ですか?)。

echo <(ls -l)出力をとして与えます/dev/fd/63

また、この出力例は私には不明確です。

ls -l <(echo "Whatever")
lr-x------ 1 root root 64 Sep 17 13:18 /dev/fd/63 -> pipe:[48078752]

ただし、指定するとls -l <()、ディレクトリの内容が一覧表示されます。

名前付きパイプの場合はどうなりますか?

回答:


37

あなたが行うと<(some_command)、あなたのシェルはカッコ内のコマンドを実行し、コマンドの標準出力に接続されているファイルディスクリプタ、と全体を置き換えます。だから、/dev/fd/63あなたのLSの呼び出しの出力を含むパイプがあります。

行全体がパイプに置き換えられるため、エラーが発生し<(ls -l)ます。これは、実行可能ではないコマンドとしてPermission denied効果的に呼び出そうとするため/dev/fd/63です。

2番目の例では、にcat <(ls -l)なりcat /dev/fd/63ます。catがパラメーターとして指定されたファイルから読み取ると、コンテンツが取得されます。echo一方、パラメータを「そのまま」出力するだけです。

最後のケース<()は、コマンドがないため、単に何も置き換えられません。しかし、これはシェル間で一貫性がありません。zshでは、パイプが得られます(空ですが)。

概要<(command)通常はファイルが必要なコマンドの出力を使用できます。

編集:としてジルは指摘し、これは名前付きパイプが、匿名のパイプではありません。主な違いは、プロセスが実行されている間のみ存在し、名前付きパイプ(たとえばで作成されたmkfifo)はプロセスがアタッチされないままであるということです。


5
mkfifoコンテンツなしで名前付きパイプのみを作成します。そのため、自分でそれに書き込む必要があります(例mkfifo mypipe; ls > mypipe)。はい、パイプへの書き込みは、プロセスがパイプから読み取るまでブロックされます。
crater2150 14

6
ここには名前付きパイプはありません。/dev/fd/63匿名パイプです。
ジル「SO-悪であるのをやめる」14

1
@ crater2150、@ Gilles / dev / fd / 63は、実際に名前付きパイプです。のようなものでこれを確認してくださいfile <(ls)。シェルは匿名パイプを作成しますが、ファイル記述子はの名前付きパイプとして反映され/dev/fdます。匿名パイプの場合、名前はなく、/dev/fd/63渡されるコマンドで開くことはできません。
rv

2
@rvまだ匿名のパイプです。この匿名パイプを参照するファイル名があるという事実は、それを名前付きパイプにしません。名前付きパイプは異なり、ファイルシステム上のどこかに存在し、許可と所有権などを持ち/dev/fdます。記述子も匿名パイプとソケット、ネットワークソケット、共有メモリ・セグメント、等
ジル「SO-停止さ悪」

1
なぜ63なのですか?
K3 --- rnc

-4

lsコマンドとリダイレクトの両方を誤解しています。lsコマンドラインで指定されたファイルとディレクトリを一覧表示しますが、stdinからの入力を受け入れるとは思わない。リダイレクト> >><は、ファイルを使用して入力を行い、出力を収集する方法です。


1
ここにはファイルからのリダイレクトはありません。<(…)プロセス置換です。
ジル「SO-悪であるのをやめる」14

1
@IMSoP-ジルが言ったように-その名前付きパイプではなく-その匿名パイプ。それは非常に多くのと同じであるx|yとほぼ同じで[num]<<REDIRECT、いくつかのシェルインチ 異なるのは、シェルのfdリンクのリテラル置換です- /dev/fd/63など、およびそれが行うこと-stdinで行うことです。やるecho | readlink /dev/fd/0と自分の目で確かめてください。
mikeserv 14

1
@IMSoP-それはdevリンクです-特別なファイル。ほとんどのLinuxシステムでファイル記述子を使用して同じことを行うことができます-典型的|pipesであっても、他の場所での動作は保証しません。私はあなたがどこから来たのかを知ることができますが、名前付きパイプはそれ自体とは別のものです-それはカーネル内パイプへのファイルシステム参照です- デバイスファイルではなく、通常のファイルシステム参照です。
mikeserv 14

1
@mikeserv興味深いことに、Bashのマニュアルでは/dev/fd/*他の場所に名前付きパイプを作成することなく、システム上で動作することに言及しています。しかし、私/dev/fd/*はそれ自体が固有の名前付きパイプとは異なるメカニズムであるという点を取り上げます。ちなみに、ウィキペディアの説明は、この区別の説明と関係がある可能性があります。
IMSoP 14

1
@mikeserv私が見つけた他の参考文献によると、それはそれよりも簡単です:/dev/fd/*利用できない場合、bashは名前付きパイプをに作成し、/tmp代わりにプロセス置換に使用します。できるだけ多くの環境で機能を利用できるようにするだけで、私にはそれほど奇妙に思えません。
IMSoP 14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.