標準入出力・リダイレクション・パイプ
Linuxのキモである「標準入出力・リダイレクション・パイプ」について調べた。
標準入出力
標準入力 【 standard input 】 stdin
標準入力とは、コンピュータ上で実行されているプログラムが、特に何も指定されていない場合に標準的に利用するデータ入力元。コンピュータの入力装置やOSが提供するデータ入力機能・経路などを指し、多くのシステムではキーボード装置による利用者の文字入力が標準入力に設定されている。システム上では “stdin” の略号で表されることが多い。
標準出力 【 standard output 】 stdout
標準出力とは、コンピュータ上で実行されているプログラムが、特に何も指定されていない場合に標準的に利用するデータ出力先。コンピュータの出力装置やOSが提供するデータ出力機能・経路などを指し、多くのシステムではディスプレイ装置による利用者への文字表示が標準出力に設定されている。システム上では “stdout” の略号で表されることが多い。
標準エラー出力 【 standard error 】 stderr
基本的に標準出力と同じだが、エラーメッセージや診断メッセージの出力に特化したデータ出力先。標準出力とは独立しているため通常の出力結果はファイルに出力して、エラーメッセージはディスプレイに表示させるということが可能。
つまりまとめると…
標準入出力とは、デフォルト(=特に何も変更しなかった場合)で標準として利用するデータの入力元、出力先のこと。
標準入力、標準出力、標準エラー出力の3つに分類され、多くのシステムでの標準入力はキーボード、標準出力と標準エラー出力はディスプレイとなっている。
Linuxでは標準入出力を以下の番号で識別している。
入出力 | 番号 | 装置 |
---|---|---|
標準入力 | 0 | キーボード |
標準出力 | 1 | ディスプレイ |
標準エラー出力 | 2 | ディスプレイ |
実行結果
キーボード(=標準入力)から「echo hello world」と入力すると、ディスプレイ(=標準出力)に「hello world」と出力される。
$ echo hello world hello world
リダイレクト
リダイレクトは標準入力、標準出力、 標準エラー出力を切替える機能のことで、リダイレクションとも呼ばれる。
通常はキーボード(=標準入力)から入力したコマンドが実行された結果をディスプレイ(=標準出力)に出力するが、リダイレクションすることで
- キーボード(=標準入力)から入力したコマンドが実行された結果を、ファイル(=標準出力)に保存する
- ファイル(=標準入力)から読み込んだデータを、別なファイル(=標準出力)に保存する
というようなことができるようになる。
1) コマンド > file
コマンドの標準出力をfileに書き込む。既存データが存在する場合は上書きされる。
以下はキーボードから「Hello World」と入力した結果をHello.txtというファイルに出力している。
$ echo Hello World >Hello.txt $ cat Hello.txt Hello World
2) コマンド >> file
コマンドの標準出力をfileに追加する。「>」は「1>」の省略形。1は標準出力の番号。
以下は1)を実行した後に、キーボードから「Close World」と入力した結果をHello.txtというファイルに出力(追加)している。
$ echo Close World >> Hello.txt $ cat Hello.txt Hello World Close World
3) コマンド < file
コマンドはfileの内容を標準入力として受け取る。「<」は「0<」の省略形。0は標準入力の番号。
以下は2)を実行した後に、Hello.txtの中身を「Hello」でgrepした結果をディスプレイに出力している。
$ grep Hello < Hello.txt Hello World
4) コマンド 2> file
コマンドの標準エラー出力をfileに書き込む。
エラーが発生しない場合は、出力先のファイルには空のデータが書き込まれるため、結果として空ファイルが作られる。
◯エラーが発生する場合の例
aaaファイルは存在しないのでerr.txtにエラーが出力される
$ ls aaa 2> err.txt $ cat err.txt ls: 'aaa' にアクセスできません: そのようなファイルやディレクトリはありません
◯エラーが発生しない場合の例
aaaファイルを作成してからlsコマンド実行。err.txtは空データで上書きされるためcatで中をみても何もない。
$ touch aaa $ ls aaa 2> err.txt aaa $ cat err.txt $
5) コマンド > file 2>&1
標準エラー出力の出力先を、標準出力の出力先にマージする。
書き方 | 説明 |
---|---|
1>&2 | 標準出力を、標準エラー出力にマージする |
2>&1 | 標準エラー出力を、標準出力にマージする |
以下は「 aiueo」と書かれているaaaファイルと、存在しないbbbの中身を、catで表示しようとしている例。cat aaa
の実行結果とcat bbb
の実行結果(この場合はファイルが存在しないエラー)が一緒にresult.txtに出力される。
$ echo aiueo >aaa $ cat aaa bbb >result.txt 2>&1 $ cat result.txt aiueo cat: bbb: そのようなファイルやディレクトリはありません
パイプ
コマンドの 出力を、直接他のコマンドの入力にすることできる機能。
例えば、ファイル(aaa,bbb,ccc)を降順に並び替えてディスプレイに表示したい場合、
- lsコマンドの実行結果をlist.txtに出力
- list.txtの中身をSortの降順に並び替えた結果をsort.txtに出力
というように中間ファイルを介して処理を行うことになり、コードが増えたり中間ファイルを削除する処理が増える。
$ ls >list.txt $ sort -r list.txt > sort.txt $ cat sort.txt sort.txt list.txt ccc bbb aaa
これをパイプを利用して、「lsコマンドの出力結果」を次の「Sortコマンドの入力」にすると以下のように1行で書くことができ中間ファイルも必要ない。
$ ls | sort -r ccc bbb aaa
書き方の例は以下の通り。
1) command1 | command2
command1の標準出力をcommand2の標準入力にわたす。command1の標準エラー出力はcommand2にはわたらない。
2) command1 |& command2
command1の標準出力と標準エラー出力をcommand2の標準入力にわたす。
3) パイプは何個でも続けることができる
command1 | command2 | command3 | ...
スペシャルファイル
スペシャルファイルとは、ファイルシステム上であたかも通常のファイルのような形で提示されるデバイスドライバのこと。
この中でもリダイレクトによく使われる「/dev/null」は、スペシャルファイルのうち「擬似デバイス」に分類され、実際の周辺機器ではない架空のデバイスである。
/dev/null
そこに書き込まれたデータを全て捨て、読み出しても何も返さない仮想デバイス。
よくブラックホールとかゴミ箱と表現されている。 なので、必要のないデータを捨てたい時に「/dev/null」にリダイレクトするという使い方をすることが多い。
以下を実行すると実行結果を全てゴミ箱に捨てるイメージ。
$ ./test.sh > /dev/null 2>&1
「全部ゴミ箱に捨てたいときは/dev/null 2>&1
」ってまる暗記してもいいみたい*2だけど、そもそもの意味を知りたいときはここに詳しく書いてあった。
*2:逆(1>&2)はだめらしい。https://qiita.com/ryskiwt/items/d4e7846fd47364a2a4e2