パイプラインは小さなコマンド同士を接続し、中間ファイルを使わずにデータを流します。tee コマンドを使うと、その流れを先へ送りながら一部をファイルへコピーできます。
テキスト操作 · レッスン 4
パイプと tee
パイプラインがコマンド同士を接続する仕組みと、tee でストリームを先へ渡しながら保存する方法を学びます。
| でコマンドを接続する
ディレクトリ一覧が長すぎて一度に読めない場合を考えます。
$ ls -la /etc
パイプ演算子 | をコマンド間に置くと、左側の stdout が右側の stdin へ接続されます。
$ ls -la /etc | less
シェルはパイプラインのコマンドを起動し、ストリームを接続します。コマンドは並行して動作でき、ls が一覧全体を生成する前に less は読み始められます。
ls -la /etc | less で、| が標準で接続するストリームはどれですか?
stderr を分けておく
通常の | が運ぶのは stdout だけです。左側の stderr は以前の出力先(多くは端末)を保ちます。
$ find /etc -name "*.conf" | less
一致したパス名はパイプを通り、権限に関する診断は端末へ直接表示されることがあります。別の動作が必要なら stderr を個別にリダイレクトします。
$ find /etc -name "*.conf" 2> find-errors.log | less
find /etc -name "*.conf" | less で他のリダイレクトがない場合、find の stderr は通常どこへ送られますか?
tee でストリームをコピーする
tee は stdin を読み取り、指定した各ファイルへコピーすると同時に、同じデータを stdout へも書き出します。
$ ls | tee listing.txt
listing.txt に一覧が保存され、tee の stdout は端末に接続されたままです。tee は標準では > と同様に指定ファイルを作成または切り詰めます。
generate-report の出力を表示し、同じ出力で report.txt を置き換えるコマンドはどれですか?
ファイルを置き換えず追記する場合は -a を使います。
$ date | tee -a activity.log
現在の日付を表示し、activity.log へ追記するコマンドはどれですか?
中間結果を保存する
tee をパイプラインの途中に置くと、中間ストリームを保存しながら処理を続けられます。
$ ls -la /etc | tee etc-listing.txt | grep "conf"
このパイプラインは次の処理を行います。
- 詳細な一覧全体を生成する。
- その完全なストリームを
etc-listing.txtに保存する。 - 同じストリームを
grepへ送り、confを含む行だけを表示する。
ファイルには grep で絞り込む前のデータが入ります。絞り込まれた行だけを保存したい場合は、tee を grep の後ろに置きます。
produce | tee all.txt | grep error が正常に終了した後、all.txt には何が入っていますか?
パイプラインとストリームのコピーを練習するには、次のハンズオンラボを試してください。
- Linux における入出力のリダイレクト - 標準出力、標準エラー、標準入力を操作してデータフローを制御します。
- シーケンス制御とパイプライン - コマンドの実行順序やパイプライン、
cut、grep、wc、sort、uniqなどのツールを学びます。 - データストリームのリダイレクト - 標準入力、出力、エラーの操作や出力の結合、
/dev/nullの利用を学びます。
レッスン完了
パイプと tee を完了しました
コマンドを接続し、データストリームの必要な地点を保存できるようになりました。
あるコマンドの stdout を別のコマンドの stdin へパイプする。
必要に応じて stderr を個別にリダイレクトする。
teeで入力をファイルと stdout の両方へコピーする。ファイルを置き換えず
tee -aで追記する。フィルターの前後どちらに
teeを置くか意図的に選ぶ。