Table of Contents
はじめに: 標準入出力とリダイレクトの関係
コンピューターの世界には, データの「入力」と「出力」という流れ(=Data Streams)があります. 特に, キーボードからの入力を標準入力, ディスプレイへの出力を標準出力と呼びます.
多くのコマンドは, 何も指定しなくても実行結果をディスプレイに表示しますが, これは標準出力としてディスプレイを使うことが デフォルトとして設定されているためです.
一方, この標準出入力先を変更する機能のことをリダイレクトといいます. 標準出入力とリダイレクトを理解することで, コマンドがなにを出力するのかをコントロールできます.
標準出入力
Def: stdin, stdout, stderr
標準入力 | standard input, stdin | コマンドが標準的に利用するデータ入力元, 通常はキーボード |
標準出力 | standard output, stdout | コマンドが標準的に利用するデータ出力先, 通常はディスプレイ |
標準エラー出力 | standard error, stderr | コマンドのエラーメッセージは, 通常の出力とは区別されるが, 通常は標準出力同様にディスプレイ |
トラブルが起きてエラー出力を行う必要がある場合に, 標準エラー出力(=stderr)というものがあります. 通常, 標準エラー出力はディスプレイになりますが, 後に説明するリダイレクトを使用することで, ファイルに出力する使い方もあります.
ファイル記述子
全てのプロセスはファイルディスクリプタ (fd: file descriptor, ファイル記述子)というファイル書き込み用の通信チャネルを持っています.
入出力チャネル | ファイル記述子 |
---|---|
標準入力 | 0 |
標準出力 | 1 |
標準エラー | 2 |
リダイレクトとパイプ
リダイレクト
リダイレクトの代表例
< FileA |
標準入力をFileAに変更 |
> FileA |
標準出力をFileAに変更 |
>> FileA |
標準出力をFileAの末尾に追記 |
2> FileA |
標準エラー出力をFileAに変更 |
2>> FileA |
標準エラー出力をFileAの末尾に追記 |
> FileA 2>&1 |
標準出力と標準エラー出力をまとめてFileAに変更 |
&> FileA |
標準出力と標準エラー出力をまとめてFileAに変更 |
>& FileA |
標準出力と標準エラー出力をまとめてFileAに変更 |
ファイル記述子を組み合わせることでリダイレクト対象を制御することができます.
例えば, ls
の標準出力結果を fileAへ新規に書き込む場合, ファイル記述子を利用するパターンと利用しないパターンで以下のように書くことができます
1
2
3
4
5
## リダイレクトのみ
% ls > fileA
## ファイル記述子を利用
% ls 1> fileA
FileA
の内容を並び替えて, その結果を別のファイルFileB
に保存する場合
1
% sort < FileA > FileB
構文まとめ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
## CMD標準出力結果をfileAへ格納
% CMD > fileA
% CMD 1> fileA
## CMD標準出力結果をfileAへ追記する
% CMD >> fileA
% CMD 1>> fileA
## lsコマンドを実行して標準エラー出力結果(non-exist-file)のみをfileAに格納する
% ls exist-file non-exist-file 2> fileA
## lsコマンドを実行して標準出力及びエラー出力結果両方をfileAに格納する
% ls exist-file non-exist-file &> fileA
% ls exist-file non-exist-file >& fileA
% ls exist-file non-exist-file 1> fileA 2>&1
% ls > fileA exist-file non-exist-file 2>&1
## 標準出力と標準エラーのリダイレクト先を分けるとき
% CMD 1> result.txt 2> error.txt
パイプ
Def: パイプ
コマンド日よって得られた結果を別コマンドに引き渡す機能のことをパイプと呼ぶ.
CMD1
の実行結果をCMD2
の標準入力に渡す場合,
1
% CMD1 | CMD2
標準出力と標準エラー出力をまとめてパイプで渡したい場合は, 2>&1 |
, または |&
を用います.
sed
コマンドに引数を渡さずに実行すると, 標準エラー出力として使用方法が出てきますが, そのラインをカウントしたい場合は
1
2
3
4
5
## 標準エラー出力用のパイプ
% sed |& wc -l
## ファイル記述子とパイプの組み合わせ
% sed 2>&1 | wc -l
Tips: 実務で役に立つ事例集
エラーメッセージを出力しない
エラーメッセージをterminalへ出力したくない場合は 2> /dev/null
で標準エラーメッセージを /dev/null
へリダイレクトします.
Def: 疑似ファイルデバイスとしての/dev/null
Linux系OSでは /dev/null
という疑似デバイスファイルを用意してある.
/dev/null
に書き込まれたデータはすべて破棄され, どこからどれだけ読み込んでも何もデータを返さない.
標準出力と標準エラー出力両方を出力させない場合は以下のようにリダイレクトを用います
1
2
3
4
## 標準出力と標準エラー出力両方を出力させない場合
% echo 'stderr' >& /dev/null
% echo 'stderr' &> /dev/null
% echo 'stderr' > /dev/null 2>&1
エラーメッセージのみ出力させたくない場合は
1
% echo 'stderr' 2> /dev/null
エラーメッセージのみ出力させる場合
- 標準出力結果を
/dev/null
へ捨てる - 標準エラー出力を標準出力へ渡す
という形で実行します
1
2
3
4
5
## CMD1のエラー出力のみをCMD2へ渡す
% (CMD1 > /dev/null) |& CMD2
## CMD1のエラーを標準出力, 標準出力を/dev/nullに捨てる場合
% (CMD1 2>&1 1> /dev/null) | CMD2
注意点として, 2つ目の例と似てるけれども違う挙動してしまうのが
1
% (CMD1 1> /dev/null 2>&1 ) | CMD2
これは先に標準出力先が先に/dev/null
となり, 標準エラーが標準出力の順番なのですべてが/dev/null
に捨てられてしまう設定になります.
例: poetryで標準エラー出力のみを出力する場合
poetry
コマンドを用いるときなど, 標準出力結果には興味がないがエラーだけ知りたいという場合があります.
この場合は
1
2
3
% poetry update 1> /dev/null
% poetry update > /dev/null
% poetry update 2>&1 1> /dev/null
どちらも標準出力結果を/dev/null
に捨てる一方, 標準エラーはちゃんと端末に出力されます.
ファイルへの書き込みと標準出力を同時に行う: tee
コマンド
Def: teeコマンド
tee
コマンドは, 標準入力から読み込んだデータを標準出力とファイルの両方に出力するコマンド
1
% tee [option] file_name
-a
オプションを加えることでファイルに追記することができる.
/etc/passwd
ファイルの内容に行番号を付け, その結果をパイプを通してファイルへ出力し, さらにその結果をパイプでhead
コマンドに渡したいとします.
1
2
3
4
5
6
7
8
9
10
% nl /etc/passwd | tee test.txt | head -3
1 root:x:0:0:root:/root:/usr/bin/zsh
2 daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
3 bin:x:2:2:bin:/bin:/usr/sbin/nologin
% cat test.txt
1 root:x:0:0:root:/root:/usr/bin/zsh
2 daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
3 bin:x:2:2:bin:/bin:/usr/sbin/nologin
...
50 vboxadd:x:495:1::/var/run/vboxadd:/bin/false
References
(注意:GitHub Accountが必要となります)