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



我想将bash脚本中printf的输出定向到stderr而不是stdout

我不是在询问重定向stderrstdout它们当前路由的位置。我只是希望能够将输出从printf发送到stderr而不是默认的stdout

我做了一些实验,发现将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)" 

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

似乎上述内容只有在 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

我希望上面的printf命令没有输出,因为输出应该转到stderr,而又应该转到文件。但这不会发生。哼?

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

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

1>&2的意思是"让FileHandle 1指向FileHandle 2当前所做的任何地方"——也就是说,本来应该写到stdout的东西现在变成了stderr。 2>errors.txt的意思是"打开一个文件句柄来errors.txt并使文件句柄 2 指向它"——也就是说,本来应该写到 stderr 的东西现在变成了errors.txt。但是文件句柄 1 根本不受影响,所以写到 stdout 的东西仍然会转到 stderr。

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

  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.
    

典型的习语是:

echo foo >&2           # you don't need to specify file descriptor 1
echo foo > /dev/stderr # more explicit, but wordier and less portable

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

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

$ printf "Hello World!" >&2

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

$ exec >&2
外壳

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

相关内容

  • 没有找到相关文章

最新更新