概要
LPIC Lv.1の勉強をしていて、のっけからリダイレクトで詰まったから。
ls > hoge.txt 2>&1
の&が分からんかった。
ググったら書いてあったので、メモ。
前提
リダイレクトとは、的なことから
標準出力
linuxではコマンドなどの入出力は主に次の3つに分類することができる。
- 標準入力
- 標準出力
- 標準エラー出力
それぞれ見たとおりで、順にコマンドに渡す入力、コマンド成功時の出力、エラー時の出力となる。
デフォルトでは、標準入力はキーボードから入力した文字が指定されている。
標準出力は画面に表示される。標準エラー出力も画面だ。
なにげなくコマンドを実行したら普通に画面に結果が表示されるのは、標準出力や標準エラー出力が画面に対して結果を渡していたからのようだ。
リダイレクト
だけれども、時には入力や出力先を変えたくなる。
コマンドでなんやらした結果をファイルに書き込みたいとか、そんな時だ。
で、登場するのが「<」や「>」といった記号を使ったリダイレクト。
こいつを使えば、出力先や入力元を指定することができる。
例
ls / > root.txt
こうすれば、root.txtにルートディレクトリの中身の一覧が格納される。
エラーをファイルに書き込むこともできる。
cat / 2> err.txt
err.txtには、たぶんこんな内容がかかれている。
cat: /: Is a directory
なんで?
実は、コマンドの入出力にはファイル記述子と呼ばれる番号が振られている。
これを利用して、入出力の指定をできるのだ。
input / output | file descriptor |
---|---|
標準入力 | 0 |
標準出力 | 1 |
標準エラー出力 | 2 |
&マークの仕事
ここで、冒頭のコマンドを見てみる。
ls > hoge.txt 2>&1
コマンドは、基本的に左から実行されるから、とりあえずlsの標準出力をhoge.txtにリダイレクトして書き込んでいるのはわかる。
だが、そのあとが謎だ。
いろいろ調べた結果、こういうことらしい。
これで出力ファイル・ディスクリプタ(記述子)の複製を行います。
したがって、
2>&1
この場合、ファイル・ディスクリプタ2に、ファイル・ディスクリプタ1の複製を使用するという意味になります。
なんのこっちゃ。
上記のエントリの助言に従って、bashのマニュアルを見てみた。
man bash
の中に次の記述を発見。
Note that the order of redirections is significant. For example, the
command
ls > dirlist 2>&1
directs both standard output and standard error to the file dirlist,
while the command
ls 2>&1 > dirlist
directs only the standard output to file dirlist, because the standard error was duplicated from the standard output before the standard output was redirected to dirlist.
ざくっと内容を抽出すると、「&1」は lsの標準出力先をコピーしているという意味らしい。今回の場合
ls > dirlist 2>&1
lsコマンドの標準出力がdirlistというファイルに向いているので、2>&1は、ファイル記述子の2番、つまりlsの標準エラー出力を、標準出力の向き先であるdirlistにリダイレクトするということらしい。
一方で、
ls 2>&1 > dirlist
はうまく動かない。なぜなら、コマンドは左から順に解釈されるので、ls 2>&1はもとのlsコマンドの出力先にしかならない。 ファイル記述子を指定しない「>」記号が定義するのは標準出力なので、結果としてこのコマンドは、うまく言った結果はファイルに記録され、エラーの場合は画面に表示するというコマンドになっている。
感想
linuxコマンドは、むずかしいけどたのしいです。