33

我想将脚本printf中 a的输出定向到而不是.bashstderrstdout

不是在询问是否重定向它们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)" 

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

上面的内容似乎只有在 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,然后应该去一个文件。但这不会发生。嗯?

4

4 回答 4

41

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

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

1>&2意思是“使文件句柄 1 指向文件句柄 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 指向的位置现在”。

于 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

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

printf 命令总是将正常输出发送到它的标准输出。这就是 printf 所做的。为了实现您想要的,您必须让 shell 安排 stdout 临时指向您想要输出的任何位置。注意我说的是暂时的。当您键入类似的命令时

$ printf "Hello World!" >&2

shell 在 printf 语句执行期间修改标准输出句柄。然后 shell 在继续执行下一个命令之前恢复 stdout 的原始值。事实上,如果你想永久重定向标准输出,你可以使用特殊命令

$ exec >&2

在 shell 执行此操作后,shell 不再记住 stdout 句柄的原始值。

于 2016-04-25T01:13:36.193 回答