質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
bash

bash(Bourne-again-Shell)は sh(Bourne Shell)のインプリメンテーションに様々な機能が追加されたシェルです。LinuxやMac OS XではBashはデフォルトで導入されています。

Q&A

解決済

1回答

676閲覧

shellのリダイレクトの挙動について

tttniaeefe

総合スコア13

bash

bash(Bourne-again-Shell)は sh(Bourne Shell)のインプリメンテーションに様々な機能が追加されたシェルです。LinuxやMac OS XではBashはデフォルトで導入されています。

2グッド

0クリップ

投稿2024/03/23 04:48

編集2024/03/23 09:32

以下のコマンドの実行結果の解釈についてご教授お願いいたします。

  1. (ea "error" 2>&1) > a.txt
  2. ea "error" 2>&1 > a.txt

質問内容
・1のコマンドの実行した際画面上に何も表示されないのはなぜでしょうか。(ea "error" 2>&1)を実行すると、標準エラー出力が画面上に表示されているので、表示されると想定していました。
・1と2において、実行後に画面上の出力の表示有無が異なるのはなぜでしょうか。
・2において、a.txtの中身が空になるのはなぜでしょうか。標準出力エラーを標準出力に出力するので、"error"が書かれていると思いますが。。

※eaというコマンドは存在しません。わざとbashのエラーを発生させているだけです。

melian, ikedas👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ikedas

2024/03/23 09:06

eaというコマンドがあるのを知りませんでした。どのような動作をするものなのか、質問文を編集して書き足してほしいです。
guest

回答1

0

ベストアンサー

まず予備知識ですが、Unix系OS (Linuxなど) の場合、コマンドラインでのデータの入出力先は「ファイルディスクリプタ」(「ファイル記述子」とも言う) というもので管理されます。これは整数で、入出力先がコンソールであろうとファイルであろうとそれぞれに固有のファイルディスクリプタが与えられます。
特に標準入力、標準出力、標準エラー出力は特別で、最初はそれぞれ012というファイルディスクリプタが与えられることに決まっています。

さて、bashのマニュアルを読むと、(...) は次のように説明されています。

(list)
list is executed in a subshell environment (中略). Variable assignments and builtin commands that affect the shell's environment do not remain in effect after the command completes. The return status is the exit status of list.

(...)の中のコマンドのリストはサブシェル環境で実行されるとのことです。したがって

(ea "error" 2>&1) > a.txt

この場合、まず「ea "error" 2>&1」がサブシェルで実行されます。これはeaコマンドを実行する前に標準エラー出力を標準出力にリダイレクト (ファイルディスクリプタ21に向け変える) しています。従って、サブシェル内でのコマンド実行 (の失敗) によってファイルディスクリプタ1にエラーメッセージが出力されます。

しかし、メインシェルの側では標準出力をファイルにリダイレクト (ファイルディスクリプタ1を出力先のファイルディスクリプタに向け変える) しています。

結果として、エラーメッセージの出力はファイルに向かい、画面には何も出力されません。

いっぽう、

ea "error" 2>&1 > a.txt

この場合、eaを実行する前に標準エラー出力を標準出力にリダイレクト (ファイルディスクリプタ21に向け変える) しています。それだけでなく、実行前には標準出力もファイルにリダイレクト (ファイルディスクリプタ1を出力先のファイルディスクリプタに向け変える) しています。

つまり、eaを実行する前に

  • 標準エラー出力はファイルディスクリプタ1 (元の標準出力) へ
  • 標準出力はファイルへ

と向け変えられているわけです。

結果として、エラーメッセージの出力は画面へ向かい、ファイルには何も出力されません。

さらに、こういうこともできます。

ea "error" > a.txt 2>&1

この場合、eaを実行する前に標準エラー出力をファイルにリダイレクト (ファイルディスクリプタ1を出力先のファイルディスクリプタに向け変える) しています。それだけでなく、実行前には標準エラー出力も標準出力にリダイレクト (ファイルディスクリプタ21に向け変える) しています。

つまり、eaを実行する前に

  • 標準出力はファイルへ
  • 標準エラー出力はファイルディスクリプタ1が向け変わったファイルへ

と向け変えられます。

結果として、エラーメッセージの出力はファイルへ向かい、画面には何も出力されません。また、仮にeaの実行が成功して標準出力にも何か出力されていたとしても、それもやっぱりファイルに書き込まれます。

投稿2024/03/23 09:49

編集2024/03/23 09:58
ikedas

総合スコア4347

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tttniaeefe

2024/03/23 12:30

解答ありがとうございます。 2>&1の位置によって挙動が変わるのがいまいち理解できておりません。 ea "error" > a.txt 2>&1  ・標準エラー出力はファイルディスクリプタ1が向け変わったファイルへ →なぜファイルへ向かうことになるのでしょうか。
ikedas

2024/03/23 13:42 編集

ああ、これ、わかりにくいですね。 リダイレクトが重なった場合、実際には右側のリダイレクトから順に適用されると考えるといいです。 ea "error" > a.txt 2>&1  この場合、2>&1 でファイルディスクリプタ2を1に向け直し、次に > a.txt でファイルディスクリプタ1を出力先のディスクリプタに向け直す。そう考えると、標準出力と標準エラー出力のどちらもファイルに向くことになります。 一方 ea "error" 2>&1 > a.txt だと逆の順序になりますから、標準出力がファイルに向き、標準エラー出力は標準出力に向くことになります。
ikedas

2024/03/23 15:15

ばれたか(^^;)。 > ここで、リダイレクトは左から右に評価されることを強調しておきたい。たまに見る「リダイレクトは右から左に評価される」という説明は誤りだ。 そうです。そう考えると辻褄が合うというだけです。 実際には、リダイレクトはdupシステムコールを使ってファイルディスクリプタを複製することによって実現しています。ですからリダイレクトというのは「出力先を向き直す」のではなく、実際には「出力元を付け替える」と言える処理をしています。 そのため、リダイレクトを「出力先を向き直す」と捉えていると、複数のリダイレクトが重なったときに逆順に適用されるように見えます。
tttniaeefe

2024/03/24 02:49

そうだったんですね。 回答いただきありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問