在C shell中将标准错误输出重定向到标准输出

76

当我在csh中运行以下命令时,什么都没有输出,但是在bash中可以正常工作。 在csh中是否有相应的命令可以将标准错误重定向到标准输出?

somecommand 2>&1

8
CSH很危险。尽量切换到bash或zsh。http://www.faqs.org/faqs/unix-faq/shell/csh-whynot/ - SS Hegde
@SSHegde,你所说的“危险”是什么意思? - Géza Török
@Geza:请参考我在评论中提到的链接,那里有解释。 - SS Hegde
@SSHegde,我希望我能够给您的“csh-whynot”链接点赞。 - Trevor Boyd Smith
6个回答

96

csh shell一直以来都不因在重定向过程中能够广泛处理文件句柄而闻名。

您可以使用以下命令将标准输出和错误输出同时重定向到一个文件中:


xxx >& filename

但这并不是你想要的,将标准错误重定向到当前标准输出。


然而,如果你所使用的操作系统在文件系统中暴露了进程的标准输出(正如Linux使用/dev/stdout),你可以按照以下方式使用该方法:

xxx >& /dev/stdout

这将强制标准输出和标准错误输出到与当前标准输出相同的位置,有效地实现了您在bash重定向中使用的2>&1

但请记住,这不是的功能。如果您运行的操作系统未公开标准输出作为文件,则无法使用此方法。


然而,还有另一种方法。如果将两个流合并为一个,并使用|&将其发送到管道中,那么您只需要找到一个管道组件,该组件将其标准输入写入其标准输出即可。如果您不知道这样的东西,那么cat正好符合要求,如果不给它任何参数,它就会执行此操作。因此,在这个特定情况下,您可以使用以下命令完成您的目标:

xxx |& cat
当然,也可以在 csh 脚本中运行 bash (假设系统中有它)来获得更多功能。然后您可以使用该shell的丰富重定向功能来处理 csh 可能无法处理的更复杂的情况。
让我们更详细地探讨这一点。首先创建一个可执行的 echo_err ,它将字符串写入 stderr
#include <stdio.h>
int main (int argc, char *argv[]) {
    fprintf (stderr, "stderr (%s)\n", (argc > 1) ? argv[1] : "?");
    return 0;
}

然后是一个控制脚本test.csh,它将展示其工作方式:

#!/usr/bin/csh

ps -ef ; echo ; echo $$ ; echo

echo 'stdout (csh)'
./echo_err csh

bash -c "( echo 'stdout (bash)' ; ./echo_err bash ) 2>&1"

使用 echo 命令和 ps 命令,只是为了确保运行此脚本的是 csh。当您使用以下命令运行此脚本时:

./test.csh >test.out 2>test.err

(在csh开始运行脚本之前,bash设置了初始重定向),如果检查out/err文件,你会看到:

test.out:
    UID     PID    PPID  TTY        STIME     COMMAND
    pax    5708    5364  cons0      11:31:14  /usr/bin/ps
    pax    5364    7364  cons0      11:31:13  /usr/bin/tcsh
    pax    7364       1  cons0      10:44:30  /usr/bin/bash

    5364

    stdout (csh)
    stdout (bash)
    stderr (bash)

test.err:
    stderr (csh)

您可以看到,test.csh 进程当前运行在 C shell 中,并且从其中调用 bash 将为您提供重定向的全套 bash 强大功能。

bash 命令中的 2>&1 让您很容易地将标准错误重定向到当前的 标准输出(按需求),无需事先知道标准输出的位置。


嗨,这可以通过修改bioffe的响应来使用csh完成。您想要的是将stderr和stdout流合并,并且不是到文件中。因此,请执行“xxx |& tee /dev/null”,这将具有合并流的效果,将它们发送到虚拟文件,但也将两者都发送到屏幕上的STDOUT(或您正在使用的任何地方)。请使用此选项更新此答案。 - mdiehl13
@mdiehl13,实际上,这是一个很好的观点,而且我之前没有考虑过。但是,我不确定tee是正确的工具。通过tee将数据同时发送到标准输出和/dev/null与通过cat仅发送到标准输出没有任何区别。所以我用那个选项更新了它,但是感谢您的信息,它帮了我很大的忙。 - paxdiablo
“cmd >& /dev/stderr” 这个命令实际上完全搞砸了我的NoMachine会话,尽管该命令是在该会话的远程系统上执行的。我曾经赞过这个答案,所以可以推断它在过去是有效的,但我提供这个第二意见来提醒大家注意。 - esmit

44

我反对上面的答案,并提供自己的观点。 csh确实具有此功能,以下是如何实现:

xxx |& some_exec # will pipe merged output to your some_exec 
或者
xxx |& cat > filename

或者,如果你只想合并流到stdout而不是重定向到文件或某些执行:

xxx |& tee /dev/null

1
@chris,这使您可以将stdout和stderr发送到同一位置,但它 允许您将标准错误管道化到 当前 标准输出。所以务必投票支持,只需意识到它并不能回答这个问题。除非使用临时调用 bash shell 的欺骗方法,否则无法使用 csh 来完成OP所要求的操作。 - paxdiablo
2
虽然在csh中没有确切的等效物,但您的答案仅涵盖了当您想要将stdout和stderr重定向到文件时的用例。此答案还演示了如何将它们重定向到管道中。 - chris
@chris,这个问题要求将stderr直接重定向到当前的stdout,而不是将它们都重定向到一个全新的位置(无论是文件还是管道)。前者可以通过我的答案的第一部分或这个答案来完成,但csh无法完成前者。如果您阅读了我的答案的第二部分(从csh暂时调用bash,并现在扩展为具体示例以希望澄清),那么它可以很好地完成。 - paxdiablo
1
令人难以置信的是,这个解决方案对于 csh 来说是“最佳”的解决方案。附言:我简直不敢相信,但是通过使用 tee /dev/null 合并标准错误和标准输出的解决方案是“最佳的”。... 摇头 - Trevor Boyd Smith

41

正如paxdiablo所说,您可以使用>&来重定向标准输出和标准错误输出。但是,如果您想将它们分开,可以使用以下命令:

如上所述。

(command > stdoutfile) >& stderrfile

如上所示,它将标准输出重定向到stdoutfile并将标准错误重定向到stderrfile。


这个回答在我看来应该有更多的赞同票。但是我是否忽略了一些负面影响呢? - Martin G
这是我认为正确的答案。另一个被接受的答案并没有回答问题! - Charbel
@Charbel,它不会将stderr重定向到当前stdout,它会将两者都重定向到一个新位置。 - paxdiablo

5
   xxx >& filename

或者按照以下步骤,将所有内容显示在屏幕上并保存到文件中:

  xxx | & tee ./logfile

pfctl -t bruteforce -T expire 259200 |& tee | grep -v '0/0 addresses expired.' - muthuh

4
仅仅是这个吗?
xxx >& /dev/stdout

???


3
这确实回答了问题,但最好不要用问号提出,因为看起来发帖者不确定这是否回答了问题。 - Andre Miller

-2

我认为这是关于csh的正确答案。

xxx >/dev/stderr

在现代环境中,大多数csh实际上是tcsh:

rmockler> ls -latr /usr/bin/csh

lrwxrwxrwx 1 root root 9 2011-05-03 13:40 /usr/bin/csh -> /bin/tcsh

使用嵌入式反引号语句来表示如下:

echo "`echo 'standard out1'` `echo 'error out1' >/dev/stderr` `echo 'standard out2'`" | tee -a /tmp/test.txt ; cat /tmp/test.txt

如果这个方法对您有用,请将其升级到1。其他的建议在我的csh环境中都不起作用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接