入門編:パイプライン・リダイレクト・プロセス間通信
標準入出力の概念、ファイルや別ストリームへ出力を切り替えるリダイレクト、コマンド同士を接続するパイプライン、およびコマンド置換の仕組みを解説します。
標準入出力とファイルディスクリプタ
Unix 系 OS のプロセスは、実行時に3つの標準的な入出力ストリーム(ファイルディスクリプタ: FD)を自動的に開きます。
| 略称 | 名称 | FD 番号 | 既定の接続先 |
|---|---|---|---|
stdin | 標準入力 | 0 | キーボード |
stdout | 標準出力 | 1 | ターミナル画面 |
stderr | 標準エラー出力 | 2 | ターミナル画面 |
通常の実行結果(正常系)は stdout に、警告やエラーメッセージ(異常系)は stderr に出力されるよう設計されています。
リダイレクト構文(入出力の切り替え)
出力先をファイルに変更したり、ファイルからデータを読み込んだりする構文です。
» 出力のリダイレクト
# 標準出力をファイルに書き込む(上書き)
echo "Hello, World" > output.txt
# 標準出力をファイルの末尾に追記する
echo "New line" >> output.txt
# エラー出力のみをログファイルに保存する
ls /non_existent_path 2> error.log
# 標準出力と標準エラー出力の両方を同じファイルに保存する
make build > build.log 2>&1
# 不要なメッセージ(正常・エラーとも)を完全に破棄する
command_to_run > /dev/null 2>&1
» 入力のリダイレクトとヒアドキュメント
# ファイルの内容を標準入力として渡す
sort < unsorted.txt
# 複数行のテキストを直接渡す(ヒアドキュメント)
cat <<EOF > config.yaml
server:
host: 127.0.0.1
port: 8080
EOF
# 単一の文字列を標準入力として渡す(ヒアストリング)
grep "error" <<< "system info: unexpected error occurred"
パイプライン(|)と tee コマンド
パイプライン演算子(|)を使用すると、左側のコマンドの標準出力(stdout)を、右側のコマンドの標準入力(stdin)に直接渡すことができます。
# 実行中プロセス一覧から node を含む行を検索し、行数をカウントする
ps aux | grep "[n]ode" | wc -l
» tee コマンド(分岐)
パイプラインの途中で出力を画面に表示しつつ、同時にファイルへも保存したい場合は tee コマンドを挟みます。
# ビルドログを画面で見ながらファイルにも記録
./build.sh | tee build.log
コマンド置換とプロセス置換
コマンドの実行結果を変数に代入したり、ファイルのように扱ったりする強力な構文です。
» コマンド置換($(...))
実行結果の文字列をその場に展開します。古いバッククォート構文(`...`)に比べ、ネストが容易で可読性に優れています。
# 現在日付を変数に格納
CURRENT_DATE=$(date "+%Y-%m-%d")
echo "Backup date: $CURRENT_DATE"
# バックアップアーカイブの作成
tar -czf "backup-$(date +%Y%m%d).tar.gz" ./data
» プロセス置換(<(...))
コマンドの出力を一時的な名前付きパイプとして扱い、ファイルパスを要求するコマンドに直接渡すことができます。
# 2つのコマンドの出力結果の差分を直接比較(一時ファイルの作成が不要)
diff -u <(ls -1 dir_a) <(ls -1 dir_b)