我应该使用什么方法在bash脚本中使用'printf'将错误消息写入'stderr'?

irr*_*ohn 28 bash stderr io-redirection bash4

我想将脚本printf中的a 的输出bash指向stderr而不是stdout.

不是要求重定向stderrstdout从哪里重定向到当前路由.我只是希望能够将输出从a发送printfstderr而不是默认值stdout.

我进行了一些实验,发现如下例所示,附加1>&2printf我想做的事情.但是,我没有使用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)" 
Run Code Online (Sandbox Code Playgroud)

我还有一个次要问题.我问的不是因为我需要知道,而是因为我只是好奇并希望更好地了解正在发生的事情.

看来上面只有在shell脚本中运行时才会起作用.当我从命令行尝试它时似乎不起作用.

这是我的意思的一个例子.

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
Run Code Online (Sandbox Code Playgroud)

我希望printf上面的命令没有输出,因为输出应该转到stderr,然后应该转到文件.但这不会发生.咦?

hob*_*bbs 31

首先,是的,这1>&2是正确的做法.

其次,你的1>&2 2>errors.txt例子不起作用的原因是因为重定向的确切细节.

1>&2意味着"使文件句柄1指向文件句柄2当前所处的位置" - 即那些本来写入stdout的东西现在转到stderr.2>errors.txt意思是"打开一个文件句柄errors.txt并使文件句柄指向它" - 即现在写入stderr的东西进入errors.txt.但是文件句柄1根本没有受到影响,所以写入stdout的东西仍然会转到stderr.

正确的做法是2>errors.txt 1>&2,它将对stderr和stdout进行写入errors.txt,因为第一个操作将是"打开errors.txt并使stderr指向它",第二个操作将是"使stdout指向stderr指向的位置"现在".


Car*_*rum 11

  1. 这对我来说似乎很合理.但是你不需要1它 - 它会按原样运行,但它隐含着:

    printf "{%s}   This should go to stderr.\n" "$(date)" >&2 
    
    Run Code Online (Sandbox Code Playgroud)
  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.
    
    Run Code Online (Sandbox Code Playgroud)


Tod*_*obs 7

典型的成语是:

echo foo >&2           # you don't need to specify file descriptor 1
echo foo > /dev/stderr # more explicit, but wordier and less portable
Run Code Online (Sandbox Code Playgroud)


小智 5

这个问题似乎表明了一些混乱。您不想重定向标准输出,您只想让 printf 将其输出发送到标准错误...但为此,您必须使用重定向。

printf 命令始终将正常输出发送到其标准输出。这就是 printf 所做的。为了实现你想要的,你必须让 shell 安排 stdout 临时指向你想要输出去的任何地方。注意我说的是暂时的。当你输入一个命令时

$ printf "Hello World!" >&2
Run Code Online (Sandbox Code Playgroud)

shell 在 printf 语句的执行期间修改 stdout 句柄。然后 shell 在继续执行下一个命令之前恢复 stdout 的原始值。实际上,如果要永久重定向 stdout,则使用特殊命令

$ exec >&2
Run Code Online (Sandbox Code Playgroud)

在外壳执行此操作后,外壳不再记住标准输出句柄的原始值。