リダイレクトを理解する

コマンドの結果を画面に出すだけでなく、ファイルへ保存したり次のコマンドへ渡したりすると処理を組み合わせられます。通常の結果とエラーメッセージを別の流れとして扱い、どこへ何が届くかを図と実習で確認します。実習はLinuxのBashと基本コマンドを前提にします。

この単元で学ぶこと

  • 標準入力・標準出力・標準エラーの経路を説明できる
  • 上書き・追記・パイプを使い分けられる
  • リダイレクトの順序による出力先の違いを検証できる

本文解説

三つの入出力口 コマンドには標準入力(番号0)、標準出力(番号1)、標準エラー(番号2)という入出力口があります。端末から起動したときは入力をキーボードから、結果と診断を画面で扱うことが多いですが、シェルが接続先を変更できます。結果とエラーが同じ画面に見えても、同じ口から来たとは限りません。

ファイルへ保存する printfは指定形式で文字を出力します。printf "A\n" > data.txtは標準出力をdata.txtへ接続し、既存内容を置き換えます。printf "B\n" >> data.txtは末尾へ追記します。この順番ならファイルの内容はA、Bの二行です。標準出力をファイルに向けただけでは、標準エラーの接続先は変わりません。

入力をファイルへつなぐ wc -l < data.txtはdata.txtを標準入力として読み、改行の数を数えます。前の例なら2です。wc -l data.txtも数を求められますが、後者はファイル名も表示します。<はファイル内容をコマンド名やコマンド引数へ置換する記号ではありません。

コマンドをつなぐ printf "red\nblue\nred\n" | grep "^red

quot; | wc -lでは、printfの標準出力をgrepへ、grepの標準出力をwcへ渡します。grepは行全体がredの二行を残すため、最後は2です。|だけでは左の標準エラーは右へ渡りません。フィルターにエラー文を混ぜると件数の意味が変わることがあります。

診断を分離する sh -c 'printf "OK\n"; printf "ERR\n" >&2' > out.txt 2> err.txtでは、OKはout.txt、ERRはerr.txtへ入ります。内側の>&2はprintfの出力を標準エラーへ向けます。外側の2>はその標準エラーの保存先を決めます。2>1は番号1というファイルへの保存であり、2>&1とは違います。

左から順番に接続する > all.txt 2>&1は最初に標準出力をall.txtへ向け、次に標準エラーをその時点の標準出力と同じ先へ向けます。両方がall.txtへ入ります。一方2>&1 > out.txtは、まず標準エラーを元の標準出力、通常は端末へ向け、次に標準出力だけをout.txtへ変更します。後から標準出力を変えても、標準エラーは自動で追いかけません。

画面と保存を両立する printf "A\nB\n" | tee copy.txtは二行を画面へ出しながらcopy.txtにも保存します。teeは標準入力を複数の出力先へ複製するコマンドです。追記ならtee -a copy.txtを使います。不要な診断だけを捨てる2> /dev/nullはエラーを表示しませんが、コマンドが成功したことにはなりません。

実習:準備と操作 作業専用の新しい一時ディレクトリで行います。次をBashで一行ずつ実行します。 lesson_dir=$(mktemp -d) printf "red\nblue\nred\n" > "$lesson_dir/input" grep "^red

quot; "$lesson_dir/input" | wc -l > "$lesson_dir/count" sh -c 'printf "OK\n"; printf "ERR\n" >&2' > "$lesson_dir/out" 2> "$lesson_dir/err" ファイルの出力先を毎回引用符で囲み、空白を含むパスでも一つの引数にします。

実習:成功条件と診断 cat "$lesson_dir/count"で2を確認し、grep -qx OK "$lesson_dir/out"とgrep -qx ERR "$lesson_dir/err"の各直後にprintf "%s\n" "$?"を実行して0を確認します。さらにwc -l < "$lesson_dir/out"とwc -l < "$lesson_dir/err"がそれぞれ1かを確認します。違えばcatで各ファイルを確認し、grepの抽出と保存先の指定を分けて調べます。検証後は作成したinput、count、out、errだけをrm --で指定して削除し、rmdir "$lesson_dir"で空の作業ディレクトリを削除します。

上書きと終了状態の注意 cat data.txt > data.txtは、catが読む前にシェルが出力ファイルを空にするため内容を失う危険があります。別の出力名を使って確認します。また、Bashの通常のパイプライン終了状態は最後のコマンドの状態です。途中の失敗も検出したい管理用スクリプトではset -o pipefailの意味を学びます。出力先の変更だけで失敗を成功に変えることはできません。

図解

結果と診断を別々に流す
標準出力と標準エラーを分けて保存すると、データ処理と失敗診断を区別できる。

重要ポイント

  • 0は入力、1は結果、2は診断。
  • >は置換、>>は追記。
  • |は標準出力を次の標準入力へつなぐ。
  • 2>&1は実行時点の接続先を複製するため順序が重要。
  • 出力内容と終了状態を別々に検証する。

間違えやすい点

  • 2>1を2>&1と取り違えない。
  • 入力と同じファイルを>の出力先にしない。
  • エラー文が消えたことを成功の証拠にしない。

用語解説

標準入力
コマンドが通常データを読み込む入口。番号0。
標準出力
コマンドが通常の結果を出す出口。番号1。
標準エラー
診断メッセージなどを出す出口。番号2。
リダイレクト
入出力の接続先をファイルなどへ変更すること。
パイプ
あるコマンドの出力を別コマンドの入力へ接続する仕組み。

関連教材

参考資料

教材データに登録された参考リンクです。リンク先の内容や更新日は提供元でご確認ください。

確認問題の出題・採点や学習履歴の保存にはログインが必要です。