リダイレクト演算子は常にファイル記述子を並列に開きますか?

リダイレクト演算子は常にファイル記述子を並列に開きますか?

1.抜粋#1を検討してください:

$ cat test.txt > test.txt
cat: test.txt: input file is output file

入力ファイル記述子がtest.txtを指すようにし、cat出力ファイル記述子をtest.txtに設定しようとすると、上記のエラーが発生します。リダイレクト演算子はここで知られているようですので、cat出力ファイル記述子をtest.txtに設定してください。

2.抜粋#2を考えてみましょう:

$ cat 1.txt
1:CAT
2:dog
$ sed 's/cat/CAT/g' test.txt
1:CAT
2:dog
$ sed 's/cat/CAT/g' test.txt > test.txt
$ cat test.txt # Note that test.txt is now empty
$

ここでは、ファイル出力記述子が設定されたsed読み取りモードで開かれるtest.txt(最後のパラメータ)を表示できます。test.txtさらに、演算子は'>'ファイルの読み取りを開始する前にファイルの内容を上書きします。sed

パイプラインのコマンドが並列に実行されることはわかっていますが、リダイレクト演算子の動作方法に関する情報には触れませんでした。すべてのサポートリンクが役に立ちます。

ベストアンサー1

jordanmが指摘した文書に加えて、あなたの質問に記載されている誤解を修正したいと思います。実行された手順はいいえリダイレクトを処理します。彼らもほとんど知らない。シェルはリダイレクトを処理します。

プログラムが起動すると、stdin(#0)、stdout(#1)、stderr(#2)の3つのファイルが開きます。シェルプロンプトでプログラムを実行すると、これらのプログラムが端末デバイスに接続されるため、プログラムはユーザーが入力した内容(stdin)を読み取り、出力(stdout)とエラー(stderr)を端末に印刷します。

たとえば、cat端末でこれを実行しました。どのファイルを開いたかを確認できます。tty/dev/pts/31lsof

$ lsof -a -p `pidof cat` -d0,1,2
COMMAND   PID    USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
cat     21257 anthony    0u   CHR 136,31      0t0   34 /dev/pts/31
cat     21257 anthony    1u   CHR 136,31      0t0   34 /dev/pts/31
cat     21257 anthony    2u   CHR 136,31      0t0   34 /dev/pts/31

実際、端末が3つすべてに開いていることがわかります。それでは、cat < /dev/zero > /dev/null 2>/dev/full3つすべてをリダイレクトするやや愚かな猫の呼び出しを試してみましょう。

COMMAND   PID    USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
cat     21838 anthony    0r   CHR    1,5      0t0 1030 /dev/zero
cat     21838 anthony    1w   CHR    1,3      0t0 1028 /dev/null
cat     21838 anthony    2w   CHR    1,7      0t0 1031 /dev/full

シェルは、3 つのデバイスを端末の代わりに stdin、stdout、および stderr に渡して、これらのリダイレクトを実装します。シェルはパイプを同様に実装します。試してみましょうcat | dd > /dev/null(実際にはやや愚かなパイプです):

COMMAND   PID    USER   FD   TYPE DEVICE SIZE/OFF     NODE NAME
cat     22507 anthony    0u   CHR 136,31      0t0       34 /dev/pts/31
cat     22507 anthony    1w  FIFO    0,8      0t0 56081395 pipe
cat     22507 anthony    2u   CHR 136,31      0t0       34 /dev/pts/31

COMMAND   PID    USER   FD   TYPE DEVICE SIZE/OFF     NODE NAME
dd      22508 anthony    0r  FIFO    0,8      0t0 56081395 pipe
dd      22508 anthony    1u   CHR 136,31      0t0       34 /dev/null
dd      22508 anthony    2u   CHR 136,31      0t0       34 /dev/pts/31

シェルがパイプを開き、それを使用してstdoutをcatstdinに接続する方法を確認しますdd。そしてそれがddstdoutを/dev/null

実行中のコマンドは、リダイレクトについて実際にはわかりません。彼らは通常どおりstdin、stdout、stderrを使用します。これらはすべて端末であっても、ファイル、デバイス、または他のプログラムにパイプにリダイレクトすることもできます。あるいは、シェルがサポートしている場合は、ネットワークソケットも可能です。

最も複雑なパイプでも、実際には、プログラムを実行する前にこれらの3つのファイルハンドルをリンクする方法についてのシェルのガイドラインだけです。

(注:一部のプログラムは端末に接続されているプログラムの1つを使用して動作が異なりますが、一般的に対話型の使用ではより使いやすいですls。 - 通常、他のプログラムに渡したいと思うかもしれません。

おすすめ記事