ストリームとリダイレクト
101 試験でリダイレクトが出るとき、ほぼ必ず絡むのがファイルディスクリプタの番号と書く順番です。番号は3つだけ覚えます。
| 番号 | 名前 | 既定の接続先 |
|---|---|---|
| 0 | 標準入力 stdin | キーボード |
| 1 | 標準出力 stdout | 端末画面 |
| 2 | 標準エラー出力 stderr | 端末画面 |
> は 1 のリダイレクト、< は 0 のリダイレクトの省略形です。2> と書けば標準エラー出力だけを振り分けられます。標準出力を捨ててもエラーが画面に残るのは、2 が別の口だからです。この分離のおかげで、結果はファイルに残しつつエラーだけ画面で見る、といった使い分けができます。
書き方の一覧
| 記法 | 意味 |
|---|---|
cmd > f | 標準出力を f に上書きする |
cmd >> f | 標準出力を f に追記する |
cmd < f | f を標準入力として読ませる |
cmd 2> f | 標準エラー出力を f に上書きする |
cmd 2>> f | 標準エラー出力を f に追記する |
cmd > f 2>&1 | 標準出力を f に向け、標準エラー出力もそこへ合流させる |
cmd &> f | 上と同じ意味の bash の短縮形 |
cmd > /dev/null | 標準出力を捨てる |
cmd 2> /dev/null | エラーだけ捨てる |
順番が結果を変えます
試験で最もよく出る引っかけです。次の2つは見た目が似ていますが、結果がまったく違います。
ターミナル
cmd > f 2>&1
cmd 2>&1 > f上は、先に標準出力を f につなぎ、そのあと標準エラー出力を「そのときの標準出力の接続先」つまり f につなぎます。両方が f に入ります。
下は、先に標準エラー出力を「そのときの標準出力の接続先」つまり画面につなぎ、そのあとで標準出力だけを f につなぎ替えます。標準出力は f に入り、標準エラー出力は画面に残ります。2>&1 は「今この瞬間の 1 の接続先に合わせる」という複製の指示であって、以後ずっと 1 に追随するわけではない、というのが理解の要です。
tee とパイプと xargs
パイプ | は左のコマンドの標準出力を右のコマンドの標準入力につなぎます。パイプに流れるのは 1 だけで、2 は流れません。エラーも乗せたいときは cmd 2>&1 | next と書きます。
tee は入力を画面とファイルの両方に出します。途中経過を残しつつ次に渡したいときに使い、tee -a にすると上書きでなく追記になります。
ターミナル
ls -l | tee list.txt
ls -l | tee -a list.txt | wc -lxargs は標準入力から受け取った文字列を、コマンドの引数に置き換えて実行します。rm や grep のように標準入力ではなく引数を要求するコマンドへ橋渡しするために使います。渡す相手が削除系のときは、まず無害なコマンドで対象を確かめてから置き換えてください。
ターミナル
find /tmp -name "*.tmp" | xargs ls -lヒアドキュメント
<< に続けて終端の目印を書くと、その目印が単独で現れるまでの複数行を、そのまま標準入力に流し込めます。設定ファイルを一気に書き出すときの定番です。目印は EOF でなくても構いません。<<- と書くと各行の先頭のタブが取り除かれ、目印を引用符で囲むと中の変数が展開されなくなります。
ターミナル
cat <<END > /root/memo.txt
1行目
2行目
ENDよくある引っかけ
&> を「バックグラウンド実行してリダイレクト」と読ませる選択肢が出ます。バックグラウンドは末尾の & であって、&> とは別物です。
2>&1 > f で両方がファイルに入る、という選択肢も誤りです。エラーは画面に残ります。
> と >> の違いを問う問題では、> が既存の内容を消してしまうことを忘れないでください。