33

スクリプトprintf内の aの出力をではなく に送りたい。bashstderrstdout

リダイレクトについて、または現在ルーティングされている場所からのリダイレクトについては尋ねていません。出力をデフォルトの ではなく に送信できるようにしたいだけです。stderrstdoutprintfstderrstdout

少し実験したところ、次の例に示すように、に追加1>&2すると、希望どおりに動作するように見えることがわかりました。printfただし、bash を使用した経験はありません。私の主な質問は、これを行うための「より良い」方法があるbashかどうかです。

より良い」とは、これを行うための、より一般的に使用されている、より慣習的な、またはより慣用的な別の方法があることを意味しますか? より経験豊富な bash プログラマーはどのようにそれを行うでしょうか?

#!/bin/bash
printf "{%s}   This should go to stderr.\n" "$(date)" 1>&2 
printf "[(%s)] This should go to stdout.\n" "$(date)" 

二次的な質問もあります。知りたいからではなく、単に興味があり、何が起こっているのかをよりよく理解したいからです。

上記は、シェルスクリプト内で実行された場合にのみ機能するようです。コマンドラインから試してみると、うまくいかないようです。

これが私の言いたいことの例です。

irrational@VBx64:~$ printf "{%s} Sent to stderr.\n" "$(date)" 1>&2 2> errors.txt
{Sat Jun  9 14:08:46 EDT 2012} Sent to stderr.
irrational@VBx64:~$ ls -l errors.txt
-rw-rw-r-- 1 irrational irrational 0 Jun  9 14:39 errors.txt

printf上記のコマンドには出力がないことが予想されます。これは、出力が に送信さstderrれ、次にファイルに送信される必要があるためです。しかし、これは起こりません。は?

4

4 に答える 4

41

まず、はい、1>&2正しいことです。

第二に、あなたの1>&2 2>errors.txt例が機能しない理由は、リダイレクトが正確に何をするかの詳細のためです。

1>&2これは、「ファイルハンドル 1 がファイルハンドル 2 が現在行っている場所を指すようにする」ことを意味します。つまり、標準出力に書き込まれるはずだったものが標準エラー出力に送られます。2>errors.txtは、「ファイルハンドルを開き、ファイルerrors.txtハンドル 2 がそれを指すようにする」ことを意味します。つまり、stderr に書き込まれるはずだったものがerrors.txt. しかし、ファイルハンドル 1 はまったく影響を受けないため、stdout に書き込まれたものは stderr に送られます。

正しいことは2>errors.txt 1>&2、stderr と stdout の両方への書き込みを に行うことです。これはerrors.txt、最初の操作が「開いerrors.txtて stderr がそれを指すようにする」ためであり、2 番目の操作は「stdout が stderr が指している場所を指すようにする」ためです。今"。

于 2012-06-09T18:55:51.130 に答える
17
  1. それは私には理にかなっているように思えます。ただし、必要はありません1-そのままで機能しますが、暗示されています:

    printf "{%s}   This should go to stderr.\n" "$(date)" >&2 
    
  2. 操作の順序に問題があります。

    $ printf "{%s} Sent to stderr.\n" "$(date)" 2> errors.txt 1>&2
    $ ls -l errors.txt 
    -rw-r--r--  1 carl  staff  47 Jun  9 11:51 errors.txt
    $ cat errors.txt 
    {Sat Jun  9 11:51:48 PDT 2012} Sent to stderr.
    
于 2012-06-09T18:52:45.993 に答える
7

典型的なイディオムは次のとおりです。

echo foo >&2           # you don't need to specify file descriptor 1
echo foo > /dev/stderr # more explicit, but wordier and less portable
于 2012-06-09T21:18:25.217 に答える
5

質問は混乱を示しているようです。stdout をリダイレクトするのではなく、printf にその出力を stderr に送信させたいだけです...しかし、そのためには、リダイレクトを使用する必要があります。

printf コマンドは、常に通常の出力をその stdout に送信します。それが printf の機能です。必要なものを実現するには、標準出力が出力先の場所を一時的に指すようにシェルを調整する必要があります。私が一時的に言っていることに注意してください。のようなコマンドを入力すると

$ printf "Hello World!" >&2

シェルは、printf ステートメントの実行中に stdout ハンドルを変更します。次に、シェルは、次のコマンドを続行する前に、stdout の元の値を復元します。実際、標準出力を永続的にリダイレクトしたい場合は、特別なコマンドを使用します

$ exec >&2

シェルがこれを実行すると、シェルは stdout ハンドルの元の値を記憶しなくなります。

于 2016-04-25T01:13:36.193 に答える