はじめに
Linux では、キーボードから入力されたデータ、ファイルを読み込むことで取得したデータを ストリーム として扱う。
ストリームの入力元や出力先はデフォルトで決まっているが、これを リダイレクト によって変更することで、コマンド同士を連携させて様々なスクリプトを実現することができる。
リダイレクトするためにはリダイレクト演算子を使用する。
リダイレクト演算子は、ストリームの入力元や出力先を標準(デフォルト)から変更することができる
標準入力 / stdin
Standard Input
プログラムへのデータ入力元になるストリーム。
通常は キーボード。
標準出力 / stdout
Standard Output
プログラムが実行結果の出力先となるストリーム。
通常は 端末。
$ echo
や $ printf
の実行結果は標準出力に出力されている。
$ tty
teletypewriter = tele(遠隔地の)タイプライター
現在の環境における標準出力先のデバイスファイルを表示するコマンド。
$ tty
出力される /dev/ttys000
や /dev/ttys001
などは一般に、 tty
で始まるものはローカル環境の端末、pts
で始まるものは SSH や Telnet などを経由してネットワーク越しに接続された端末を表す。
ターミナルを複数開いた場合、それぞれ異なるセッションが作成されるため、1つは /dev/ttys000
、もう1つは /dev/ttys001
などの割り当てになる。
標準エラー出力 / stderr
Standard Error
エラーメッセージや警告メッセージの出力先となるストリーム。
通常は 端末。
ファイルディスクリプタ
File Descriptor
プログラムがファイルや入出力ストリームを識別するための識別子(整数)。
標準入出力に対してはあらかじめ識別子が決まっている。
ファイルディスクリプタ | ストリーム |
---|---|
0 |
標準入力 |
1 |
標準出力 |
2 |
標準エラー出力 |
パイプ / |
Pipeline
コマンド同士を |
で連結することで、コマンドの標準出力を次のコマンドの標準入力にすることができる。
$ コマンド1 | コマンド2
$ ls | grep ".txt"
リダイレクト
リダイレクト演算子を使用して標準入力や標準出力を変更すること。
リダイレクト演算子には ファイルディスクリプタ を使用するものがある。
>
標準出力をファイルに変更する演算子。
ファイルが存在することが前提で、出力結果は上書きされる。
実行結果を標準出力へ出力するコマンド(echo
、printf
、pwd
、date
、...)に対して使用することができる。
$ コマンド > ファイル名
ファイルディスクリプタを指定すると、標準エラー出力をファイルにに変更することができる。
$ コマンド 2> ファイル名
>>
標準出力をファイルに変更する演算子。
ファイルが存在することが前提で、出力結果は末尾に追記される。
$ コマンド >> ファイル名
ファイルディスクリプタを指定すると、標準エラー出力をファイルに変更することができる。
$ コマンド 2>> ファイル名
<
標準入力をファイルに変更する演算子。
標準入力を受け取るコマンド(cat
、grep
、sort
、uniq
、wc
、cut
、tee
、head
、tail
)に対して使用することができる。
$ コマンド < ファイル名
<<
ヒアドキュメント(Here Document)を標準入力とするための機能。
<<
で指定した任意の文字列を「ヒアドキュメント開始」、「ヒアドキュメントの終了」の合図とすることができる。
文字列には End of File の頭文字をとった EOF
がよく使用される。
$ コマンド << EOF
# ヒアドキュメントとなる部分
# ヒアドキュメントとなる部分
# ヒアドキュメントとなる部分
EOF
<<
はシェルに対して「次に続く文字列(EOF
)が現れるまでを標準入力として扱う」という指示を与えている。
またヒアドキュメント内では、変数展開 や コマンド置換 を使用することができる。
2>&1
標準エラー出力を標準出力に結合する。
>
を併せて利用することで、標準出力と標準エラー出力の両方を同じ場所にリダイレクトさせることができる。
$ コマンド > ファイル名 2>&1
2>&1
が末尾につく理由
2>&1
はあくまでも「標準エラー出力」を「現在の標準出力」に合わせる効果しかない。
$ コマンド > ファイル名 2>&1
上記では、 $ コマンド > ファイル名
によって標準出力が指定したファイルに変更された後に、標準エラー出力を標準出力先に統一している。
誤って、
$ コマンド 2>&1 ファイル名
とした場合、そもそも標準出力先を変更していないので、何も変化がない。
また、
$ コマンド 2>&1 > ファイル名
とした場合も、エラー標準出力が変更されるタイミング($ コマンド 2>&1
)の標準出力は、まだリダイレクトによって変更されていないので、$ コマンド 2>&1
が何も効果を持たない。
/dev/null
特殊なデバイスファイル。
/dev/null
に送られたデータは、即座に消去され、どこにも保存されない。
保存されないため、ストリームに容量制限がなく、ストレージを占有することがない。
$ cat
concatenate
ファイルの内容を標準出力へ出力する。
$ cat ファイル名
$ cat -n ファイル名 # 行番号も表示する
$ xargs
標準入力から受け取った文字列を、別のコマンドの引数に渡しながら実行する。
パイプ と併せて利用される。
$ コマンド | xargs 実行したいコマンド # 実行したいコマンドには、先頭のコマンド実行結果が標準入力として渡る
-n
オプションを指定すると、引数を指定した数ずつ分割して渡すことができる。
$ echo "arg1 arg2 arg3" | xargs -n 1 echo
$ tee
標準入力から受け取ったストリームを、標準出力とファイルの両方へ出力する。
コマンドの実行結果をファイルに書き込みしながら、次のコマンドへと渡すことができる。
パイプ と併せて利用される。
$ コマンド | tee ファイル名 | コマンド # 最後のコマンドには、最初のコマンドの実行結果が標準入力として渡る