私は、実行可能ファイルが出力を生成するときに出力を印刷してファイルにstdout
リダイレクトし、他のコマンドにパイプできるようにすることを好みます。
実行可能ファイルが通常2つの異なるファイルにリダイレクトされる2つの異なる出力を作成する必要があるとします。ファイル名を実行可能ファイルに渡すのを避け、ファイルに直接書きたいです。代わりに、次のようなものを書きたいです。
$ program 1>file_1 3>file_2
似たようなことができますか?
答え1
できますが、良い考えではありません。通常、プログラムは3つのファイル記述子が開いた状態で起動します。
- 0 は標準入力で、何らかの方法でテキストを処理するコマンドが入力がファイルから出ない場合は入力を読み込みます。
- 1は標準出力で、コマンドで生成された一般データに適しています(データが明示的にファイルに転送されていない場合)。
- 2は、コマンドによって生成された有用なデータの一部ではない診断メッセージの標準エラーです。
これらの規則に違反し、より多くのファイル記述子を使用できますが、これは呼び出し側が正しいファイル記述子を指定した環境でのみアプリケーションを直接使用できることを意味します。アプリケーションでこれを簡単にテストすることはできません。ファイル記述子3以降は管理されていないため、アプリケーションの起動時に閉じられたり(検出可能)、関連性のない目的で開くことができます(検出できません)。 )。
コマンドラインからファイル名を渡すことは、複数の入力ファイルまたは出力ファイルを指定する一般的な方法です。
つまり、任意のファイル記述子にアクセスするには、次のようにします。
シェルから:必要な番号にリダイレクトします。例:
IFS= read -r line <&3 printf "%s\n" "$line" >&4
- Cでは、目的のfdを呼び出し、
read
使用、または呼び出してstdioストリームを取得します。write
fdopen
Perlでは、ファイルディスクリプタをコピーするために開くファイル名にシェルリダイレクトを指定するか、
=
一般的なfdopen
。open IN3, "<&=3"; open OUT4, ">&=4";
- Pythonでは
os.fdopen
。
答え2
はい、もちろん可能です。これはデフォルト値が11>file_1
に単純化されることに注意してください。>file_1
たとえば、
$ cat test.ksh
#!/bin/ksh
echo "this goes to stdout"
echo "this goes to stderr" >&2
echo "this goes to fd 3" >&3
$ ./test.ksh >file_1 3>file_2
this goes to stderr
$ cat file_1
this goes to stdout
$ cat file_2
this goes to fd 3
答え3
例に示すように、シェルから任意のファイル記述子を正確にリダイレクトできます。複数のストリームを使用するプログラムには、使用するファイル名を知らせる必要があります。プログラムがシェルを介して(おそらくパイプに)リダイレクトされたfdを使用するようにするには、/dev/fd/N
それをファイル名に渡してfd Nを使用します。