読者です 読者をやめる 読者になる 読者になる

リダイレクトの基礎復習

今までなんとなくつかっていたので、あらためて、基礎復讐。

標準入出力とファイルディスクリプタ

ファイルディスクリプタ

プロセスがなんらかのファイルやディレクトリを操作する時に利用する、正の数。
UNIXは全てのファイルとして扱うので、キーボードや端末画面すらファイルとして操作する。
その時に割り当てられているのがファイルディスクリプタ番号であり、0,1,2の三つは入出力に固定で割り当てられている

リダイレクション

リダイレクションは入出力先などを任意に変える仕組み。

lsコマンドの例

lsコマンドを普通に実行すると

1:シェルが標準入力(キーボード)からlsコマンドを実行しなさいという命令をうける
2:シェルがlsコマンドを実行し、その結果を受け取る
3:シェルは貰った結果を、標準出力(端末画面)に書きだす


ここで出力先をfileというファイルに変えてみましょう。

ls > file

このようにすると、標準出力先が端末画面からfileというファイルに変更され、lsコマンドの実行結果が、fileに書きこまれます。

標準入出力のリダイレクション一覧

  • > file
    • 標準出力の結果をファイルfileに書きこむ
  • >> file
    • 標準出力の結果をファイルfileに追加書き込みする
  • >m
    • ファイルディスクプタ番号m番の内容を標準出力にコピーする
    • 標準出力の内容をファイルディスクリプタm番に向ける
  • >&-
  • <&-

ファイルディスクリプタ番号を指定したリダイレクション

ファイルディスクリプタ番号の省略

今まで「ls > ls_list」や「cat < file」などと、「>」「<」を何気なく使ってましたが、これらはファイルディスクリプタ番号を省略した形であり、

command > file

command 1> file

と同義です。


また

command < file

command 0< file

と同義です。


0と1は良く使う&固定値なので、省略可能になっているわけです。

練習問題

今「file1」「file2」というファイルが存在するとします。
「file1」は読み込み可ですが、「file2」は読み込み不可です。

下記にコマンド例を書くので、それぞれ標準出力と標準エラー出力がどこに出力されるのか答えてみましょう

第一問
cat file* > result
第二問
cat file* 2> result
第三問
cat file* > result 2> result2
第四問
cat file* > result 2> /dev/null
第五問
cat file* > result 2> result
第六問
cat file* > result 2>> result
第七問
cat file* > result 2>&1
第八問
cat file* 2>&1 > result

練習問題の答え

第一問
cat file* > result
  • 標準出力
    • resultに出力
      • fileの内容がでる
  • 標準エラー出力
    • 端末画面
      • file2はpermission errで開けない旨
第二問
cat file* 2> result
  • 標準出力
    • 端末画面
      • file1の内容がでる
  • 標準エラー出力
    • resultに出力
      • file2はpermission errで開けない旨
第三問
cat file* > result 2> result2
  • 標準出力
    • resultに出力
      • file1の内容がでる
  • 標準エラー出力
    • result2に出力
      • file2はpermission errで開けない旨
第四問
cat file* > result 2> /dev/null
  • 標準出力
    • resultに出力
      • file1の内容がでる
  • 標準エラー出力
    • どこにもでない
      • /dev/nullにリダイレクションすると結果を捨てる
第五問
cat file* > result 2> result
  • 標準出力
    • resultに出力
      • file1の内容がでるが、すぐに消されるため確認できない
  • 標準エラー出力
    • resultに出力
      • file2を開けないエラーメッセージで、resultファイルを上書きする
第六問
cat file* > result 2>> result
  • 標準出力
    • resultに出力
      • file1の内容
  • 標準エラー出力
    • resultに追加出力
      • fiile1の内容に続いて、file2を開けないエラーメッセージを、resultファイルを追加書き込みする
第七問
cat file* > result 2>&1
  • 標準出力
    • resultに出力
      • file1の内容
  • 標準エラー出力
    • resultに出力
      • fiile1の内容に続いて、file2を開けないエラーメッセージを、resultファイルを書き込みする
第八問
cat file* 2>&1 > result
  • 標準出力
    • resultに出力
      • file1の内容
  • 標準エラー出力
    • 端末画面に出力
      • 端末画面に、file2を開けないエラーメッセージを出力

練習問題の補足

第六問と第七問の違い

第六問と第七問は結果が同じようにみえて、実は違います。
第六問は標準出力が終わってから、標準エラーを出力して追加書き込みしています。


たとえば、file1〜file100まであり、奇数の数字のファイルは読み込み不可だとしましょう。


すると、第六問のやり方では、file2〜〜file100までの偶数ファイルの内容がresultに書かれたのち、その次の行からfile1〜〜99の奇数ファイルが読み込めないエラーが書き込まれます。
一方、第七問のやり方では、標準出力の結果と標準エラー出力の結果が時系列できちんと一行ずつ書き込まれます。


多くの場合、第七問のやり方を利用する場合が多いでしょう。

第八問の解説

第八問の内部挙動の説明

  • まず、「2>&1」により、標準出力(stdout)の内容が標準エラー出力(stderr)にコピーされます
  • この段階では、標準出力も標準エラー出力も画面端末へ出力されます
  • その後、「> result」により、標準出力がリダイレクションにより result ファイルに出力されます
  • よって、標準出力はresultへ。標準エラー出力は端末画面へ。となります