一部のコマンドでBASHプロセスの置換が機能しないのはなぜですか?


29

場合によっては、プロセスの置換が期待どおりに機能しません。以下に例を示します。

入力:

gcc <(echo 'int main(){return 0;}')

出力:

/dev/fd/63: file not recognized: Illegal seek
collect2: error: ld returned 1 exit status

入力:

ただし、別のコマンドで使用すると、期待どおりに機能します。

grep main <(echo 'int main(){return 0;}')

出力:

int main(){return 0;}

私は他のコマンドで同様の失敗に気づきました(つまり、プロセス置換からのファイルを期待するコマンドは使用できない/dev/fd/63か、類似しています)。この障害gccは最新のものです。プロセスの置換がこの方法で失敗し、使用すべきでないときを判断するために知っておくべき一般的なルールはありますか?

Ubuntu 12.04でこのBASHバージョンを使用しています(archおよびdebianでもこれを見ました):
GNU bash、バージョン4.3.11(1)-release(i686-pc-linux-gnu)


1
illegal seekその答えのように見える- |pipeそれbashに実行されるプログラムを指すが、シーク可能ファイルではありません。おそらくあなたがecho data | command /dev/fd/0プログラムでうまくいかないなら、あなたは同様の運w /を持っているでしょう<(cmd)。ディスク上のファイルは提供しません-パイプファイル記述子を指す引数に置き換えるだけです。
mikeserv 14年

2
この特定のケースでは、gcc 標準入力受け入れますが、(デフォルトで)ファイル名拡張子を使用して言語を決定します。試してみてくださいgcc -xc <(echo 'int main(){return 0;}')(言語をC明示的に設定します)。
スチールドライバー14年

私は自分の質問に答えてここに導かれましたが、これは別の例のようです。superuser.com/questions/1243405。質問を私よりも上手に表現してくれてありがとう。
ジョナサンハートリー

回答:


33

プロセス置換/dev/fd/63により、名前付きパイプの読み取り終了のように動作する特別なファイルが作成されます(例のように)。このファイルは開いて読み取ることができますが、書き込むこともシークすることもできません。

引数を純粋なストリームとして扱うコマンドは機能しますが、指定されたファイルをシークする(または書き込む)コマンドは機能しません。:意志の仕事は通常のフィルタと考えられるものであることを、コマンドの種類catgrepsedgzipawk、等...仕事のようなエディタではありませんコマンドの例viなどのファイル操作mv

gcc入力ファイルに対してランダムアクセスを実行して、それらが記述されている言語を検出できるようにしたいと考えています。代わりにgcc、入力ファイルの言語に関するヒントを提供する場合は、ファイルをストリーミングできます。

gcc -x c <(echo 'int main(){return 0;}')

プロセス置換のない、より単純で単純なフォームも機能します。

echo 'int main(){return 0;}' | gcc -x c -

これはに固有ではないことに注意してくださいbash。プロセス置換をサポートするすべてのシェルは同じように動作します。


gccの回避策については+1ですが、ファイルに関するあなたのポイントについてはわかりません。<()フォーマットは、すべての意図や目的のために、ファイルのように行動しなければなりません。実際、私は満足できないファイルを期待するコマンドを知りません<()。動作しないのは、ファイルはなくファイルが必要なものです。たとえばgrep -f、ファイルを想定し、で正常に動作し<()ます。
テルドン

4
@terndon確かに<()ファイル名が生成されます(構成は/proc/self/fd/something私のシステム上で展開されます)。開かれたこの名前は、名前付きパイプの読み出し側(のように働くS_IFIFO)ではなく通常のファイル(S_IFREGその中で)サポートされread()、他はありませんseek()
セラダ14年

7
zsh特にその目的のために一時ファイルを使用するプロセス置換の3番目の形式をサポートしていることに注意してください。gcc =(echo 'int main(){return 0;}')
StéphaneChazelas 14

おそらく関連しているが、ではなく動作<(echo '...')<(git show ...)ます。なぜそうなるのでしょうか?
ヨルンヒーズ

2
GCCは、「入力ファイルに対してランダムアクセスを実行して、記述されている言語を検出しません」。ファイル名の拡張子を見るだけです。ファイル名に拡張子がない場合(または認識されない拡張子がある場合)、GCCはファイルがオブジェクトファイルまたはリンカースクリプトであると見なし、ld(オブジェクト形式を検出する)に渡します。-xヒントではありません。それは宣言です。を指定すると-x f95、GCCはファイルの名前や内容に関係なく、Fortran-95コンパイラにファイルを渡します。参照gcc.gnu.org/onlinedocs/gcc-8.1.0/gcc/Overall-Options.html
RICI
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.