
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/31
lsof
$ 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/full
3つすべてをリダイレクトするやや愚かな猫の呼び出しを試してみましょう。
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をcat
stdinに接続する方法を確認しますdd
。そしてそれがdd
stdoutを/dev/null
。
実行中のコマンドは、リダイレクトについて実際にはわかりません。彼らは通常どおりstdin、stdout、stderrを使用します。これらはすべて端末であっても、ファイル、デバイス、または他のプログラムにパイプにリダイレクトすることもできます。あるいは、シェルがサポートしている場合は、ネットワークソケットも可能です。
最も複雑なパイプでも、実際には、プログラムを実行する前にこれらの3つのファイルハンドルをリンクする方法についてのシェルのガイドラインだけです。
(注:一部のプログラムは端末に接続されているプログラムの1つを使用して動作が異なりますが、一般的に対話型の使用ではより使いやすいですls
。 - 通常、他のプログラムに渡したいと思うかもしれません。
答え2
リダイレクトの発生最初シェルに。あなたの例では:
cat test.txt > test.txt
最初に何が起こるかは、test.txt
ファイルを切り取るbash opensです。これで空で、以前はcat
パラメータとして実行されました。test.txt
Bashのマンページのリダイレクトセクションで:
シェルで解釈される特殊記号を使用して、コマンドを実行する前にコマンドの入力と出力をリダイレクトできます。リダイレクトを使用して、現在のシェルの実行環境でファイルを開いて閉じることもできます。次のリダイレクト演算子は、単純なコマンドの前、またはコマンド内の任意の場所に表示できます。リダイレクトは、表示された順序で左から右に処理されます。
POSIX 仕様には、これが最初に発生しなければならないことを示す内容はありませんが、これを行わないシェルはありません。