リダイレクトの基本
ここではリダイレクトについて説明します。
リダイレクトを理解するためには、まず標準入力とか標準出力というものを知っておく必要がありますので、まずその説明から。
標準入力、標準出力、標準エラーとは?
コマンドには「標準入力」とか「標準出力」というのがあります。
通常「標準入力」はコマンドを実行している環境でのキーボード入力のことです。ファイルデスクリプタ (FD) でいうと FD0 が標準入力です。
UNIX/Linux では入出力インターフェイスを抽象化して、ファイルデスクリプタ (FD) の数値で識別します。これにより、 ディスク上のファイルに読み書きしたり、ネットワークに接続されたソケットに読み書きしたり、ということを同様の作法で行うことができるようになってます。
「標準出力」はコマンドを実行している環境でのスクリーンへの出力のことです。ファイルデスクリプタでいうと FD1 が標準出力です。
標準入力、標準出力のほか、「標準エラー」というのもあります。これはファイルデスクリプタは FD2 です。 通常は標準出力と同じく、コマンドを実行しているスクリーンへ出力します。
ファイルの種類とデスクリプタの値をまとめると次の表になります。この値は後で使います。
ファイル名 | ファイルデスクリプタ (FD) |
---|---|
標準入力 | 0 |
標準出力 | 1 |
標準エラー | 2 |
リダイレクトとは?どうやるの?
リダイレクトというのは、標準の入出力を使うのではなく、他の入出力に切り替えることをいいます。 基本的にディスク上のファイルに出力したり、ファイルから入力を受け取ったりします。
出力をリダイレクトするには > を、入力の場合は < を使います。
例えば、環境変数 $USER を echo コマンドで出力すると、 標準出力に現在のユーザー名が出力されます。
$ echo $USER user1
これを、out という名前のファイルにリダイレクトするには > を使います。
$ echo $USER > out $ cat out user1
> を使うと元のファイルの内容は消去されます。元の内容を残し、ファイルが存在する場合に追加で書き込む場合には >> とします。
$ echo $USER >> out $ cat out user1 user1
リダイレクトによって、ファイルから入力を受け取る場合には < を使います。
$ tr 'a-z' 'A-Z' < out USER1 USER1
tr コマンドで受取った入力を変換して、小文字のアルファベットを大文字にしています。
ファイルデスクリプタを明示的に指定する
上で説明したように、リダイレクトは基本的に > で標準出力をディスク上のファイルに出力する場合と、 < でディスク上のファイルから標準入力に入力する場合に使われます。
しかし、明示的に出力先を指定する必要がある場合もあります。
例えば、cat コマンドに、存在しないファイル名を渡すと、当然ながらエラーが発生します。
$ cat XXX cat: XXX: No such file or directory
このエラーの内容を error という名前のファイルに書込むつもりで、次のようにしたとします。
$ cat XXX > error
cat: XXX: No such file or directory #リダイレクトされずにそのまま表示
$ cat error
$
しかし、error には何も書き込まれず、スクリーンにそのまま表示されてしまっています。 これはどういうことでしょうか?
この場合、エラーの内容は標準出力ではなく標準エラーに出力されています。
> は標準出力の内容をリダイレクトするのに使いますので、 標準エラーの内容はリダイレクトできなかったということです。
標準エラーをリダイレクトするためには、ファイルデスクリプタを明示的に指定する必要があります。 標準エラーのファイルデスクリプタは 2 です。従って、標準エラーをリダイレクトするには 2> とします。
従って、先ほどのコマンド例を直すと次のようになります。
$ cat XXX 2> error
$ cat error
cat: XXX: No such file or directory # 確かにリダイレクトされている
標準エラーを標準出力にリダイレクト
上の例では標準エラーをファイルにリダイレクトするために、2> としました。
さらに、もう一歩進めてみましょう。
標準エラーを標準出力にリダイレクトして、その結果をパイプ | を使って、次のコマンドに渡してみましょう。
パイプ | は標準出力の内容を次のコマンドに渡すのでしたね。詳しくは 「コマンドを組合わせる ~ パイプの基本」をみてください。
標準出力のファイルデスクリプタは 1 です。リダイレクトされた内容を標準出力で受けとるには、>&1 とします。
$ cat XXX | tr 'a-z' 'A-Z'
cat: XXX: No such file or directory # エラーは tr に渡されていない
$ cat XXX 2>&1 | tr 'a-z' 'A-Z'
CAT: XXX: NO SUCH FILE OR DIRECTORY
ディスクにリダイレクトして、さらに次のコマンドに標準出力を渡す方法
最後に、ディスクにリダイレクトした後、さらに次のコマンドに標準出力をパイプで渡す方法を紹介します。
これを行うには tee コマンドを使います。
次の例では、head コマンドでファイル file1 の 1 行目を取り出し、tee コマンドでディスク上のファイル out に書き込み、 さらに同じ内容をパイプで tr コマンドに渡して、大文字に変換しています。
$ head -n1 file1 | tee out | tr 'a-z' 'A-Z' THIS IS LINE 1. FILE1. $ cat out This is line 1. file1.
尚、tee コマンドで、元の内容を消去せずに既存のファイルに追加して書き込む場合には、-a オプションを指定します。
以上、リダイレクトについて説明しました。