2019年7月29日月曜日

Windowsコマンド:「>(リダイレクト)」で標準出力と標準エラー出力をファイルへ書き込む

「>(リダイレクト)」で標準出力と標準エラー出力をファイルへ書き込む方法


サンプル:


  dir test01 > test01.txt
  dir test02 > test02.txt 2> test02.txt
  dir test02 > test02.txt 2> test02.txt  ←×
  dir test02 > test03.txt 2> test04.txt
  dir test02 > test05.txt 2>&1

標準出力:


 標準出力とは、一言で言うと「プログラムが動作した結果や状況において“正常な状態”を“標準のデバイス”に出力する」ことを言います。
 ここで言う“標準のデバイス”は、DOSのコマンドプロンプトにおいてはディスプレイ(画面上の自身のウインドウ)を指します。
 よって、何かのコマンドを実行した結果が画面ウインドウ上に表示される状態を「標準出力」と小難しく言っただけです。
 しかしこれが意外と重要で、原理原則を理解しないと「>(リダイレクト)」を本質的に理解するのは難しくなります。


標準エラー出力:


 標準エラー出力とは、標準出力と基本的に動きは一緒ですが、2つ意味が違う部分があります。
 一つは、主にエラーや想定外の結果用の出力をするものであり、プログラム内部ではその役割をあえて分けて出力するようにプログラミングすることがほとんどです。
 二つ目に、「>(リダイレクト)」する上で、標準出力とは別に使い分ける必要があります。標準出力だけを「>(リダイレクト)」したとしても、エラーがあったときにそれは書き込まれません。エラーも書き込みたい場合はそれ相応の「>(リダイレクト)」記述をしてあげる必要があります。


 リダイレクト先についてですが、ここでは一般的なファイル(アスキーのテキストファイル)を前提に記載します。
 プリンターやテープなどの特殊なデバイスに向けたリダイレクト方法は省きます。


前提:


 以下の例では、実在するTest01というフォルダに対してdirをした場合と、実在しないTest02というフォルダに対してdirを実行した場合で試しています。



注意点:


 出力先のファイルはシングルリダイレクト(「>」)でファイルの先頭から上書きされ、ダブルリダイレクト(「>>」)でファイルの末尾に追記していきます。
 重要なファイルに誤って上書きや追記をしてしまわないよう注意が必要です。


使用例:

使用方法①:標準出力だけをテキストファイルに書き出す。

  dir test01 > test01.txt
または
  dir test01 1> test01.txt

 通常通り、標準出力結果が「test01.txt」に出力されます。
 標準エラー出力がない場合は画面に何も出ませんが、もし標準エラー出力があった場合は、例えば画面上に「ファイルが見つかりません」等のメッセージが出るだけで、ファイルには何も記述は残りません
 通常は「>」で構いません。本来の「1>」と同義です。明示的に以下の②の標準エラー出力と分けてわかりやすくしたい場合は「1>」と記述するとおお行儀は良いかもしれません。


使用方法②:標準エラー出力だけをテキストファイルに書き出す。

  dir test01 2> test01e.txt

 標準エラー出力結果が「test01e.txt」に出力されます。
 標準出力がない場合は画面に何も出ませんが、もし標準出力があった場合は、画面に表示されます


使用方法③:標準出力と標準エラー出力の両方を同名のテキストファイルに書き出す(ダメな例)。

  dir test02 > test02.txt 2> test02.txt

 これはやってはいけない方法です。標準出力と標準エラー出力を、それぞれ別のリダイレクトで出力するとファイルアクセスの競合が起きてしまいます。
 たいていの場合、「プロセスはファイルにアクセスできません。別のプロセスが使用中です。」と表示され、テキストファイルはゼロバイトの物が出来上がります。※バッチなにかを作成した場合のゼロバイトファイルはこういったチョンボで作られる場合が多いです。
 尚、同じファイルに書き出したい場合は、以下のの方法を使います。



使用方法④:標準出力と標準エラー出力の両方を別名のテキストファイルに書き出す。

  dir test02 > test03.txt 2> test04.txt

 これは問題ありません。それぞれのファイルに標準出力と標準エラー出力の情報が書き込まれます。
 ただし、デメリットがあり、エラーがあった際の流れ(タイミング)がわからなくなります
 例えば1万行の標準出力があったとして、1行だけ標準エラー出力がありそれが第二のテキストファイルに書かれていたとして、1万行の中のどのタイミングでエラーが起きたのか?はタイムスタンプでも入れていない限り判断つかなくなります。
 もし一連の流れを加味して一緒のファイルに記述した方が良いということであれば、以下のの方法がベターです。



使用方法⑤:標準出力と標準エラー出力の両方を同名のテキストファイルに書き出す(良い例)。

  dir test02 > test05.txt 2>&1

 この方法はよく使います。
 この場合、バッチで使っても、どこでエラーが起きたのか等、判断付きやすいです。
 ちなみに「2>&1」は、2>(標準エラー)の結果を、1>(標準出力)と同じデバイスに書き出しなさい、という意味と思えばよいと思います。
 ポイントは、明示的に“同じファイル”という事を指し示せているところでしょうか。上記③のダメな例では、「ファイル名が同じ」というだけであって、システム的には知らんという事になるのでしょう。

 実在しないフォルダにdirを実行し「2>&1」で出力したテキストファイルは以下のようになります。

 ドライブ C のボリューム ラベルは System です
 ボリューム シリアル番号は ****-**** です

 C:\TEMP のディレクトリ

ファイルが見つかりません

 最後の「ファイルが見つかりません」が標準エラー出力です。


 いかがでしたでしょうか。
 実際、たまにしか使わない方法なので「2>&1」をどう書くかしょっちゅう忘れてしまうことが多いです。(他のOSを触ったりすると混同してしまったり。。。)
 忘れてしまったらここを覗いて思い出す、そんな感じで。


ー PDS PIS 研究室 室長 -


0 件のコメント:

コメントを投稿