h q*_*h q 7 unix io perl stdout stderr
我希望Perl仅在STDOUT不相同的情况下写入STDERR.例如,如果STDOUT和STDERR都将输出重定向到终端,那么我不希望打印STDERR.
考虑以下示例(outerr.pl):
#!/usr/bin/perl
use strict;
use warnings;
print STDOUT "Hello standard output!\n";
print STDERR "Hello standard error\n" if ($someMagicalFlag);
exit 0
Run Code Online (Sandbox Code Playgroud)
现在考虑一下(这是我想要实现的):
bash $ outerr.pl
Hello standard output!
Run Code Online (Sandbox Code Playgroud)
但是,如果我重定向到一个文件,我想得到:
bash $ outerr.pl > /dev/null
Hello standard error
Run Code Online (Sandbox Code Playgroud)
和反过来相似:
bash $ outerr.pl 2> /dev/null
Hello standard output!
Run Code Online (Sandbox Code Playgroud)
如果我将两个/ err重定向到同一个文件,则只显示out:
bash $ outerr.pl > foo.txt 2>&1
bash $ cat foo.txt
Hello standard output!
Run Code Online (Sandbox Code Playgroud)
那么有没有办法评估/确定OUT和ERR是否指向相同的"事物"(描述符?)?
在Unix风格的系统上,您应该能够:
my @stat_err = stat STDERR;
my @stat_out = stat STDOUT;
my $stderr_is_not_stdout = (($stat_err[0] != $stat_out[0]) ||
($stat_err[1] != $stat_out[1]));
Run Code Online (Sandbox Code Playgroud)
但这不适用于Windows,它没有真正的inode数字.它给出了两个误报(认为它们不同时它们是不同的)和假否定(认为它们不相同时它们是相同的).
你可以(几乎)用 -t 做到这一点:
-t STDERR
Run Code Online (Sandbox Code Playgroud)
如果它是终端,则为 true,对于 STDOUT 也是如此。
这仍然不会告诉您哪个终端,如果您重定向到同一个文件,您仍然可能会得到两个终端。
因此,如果
-t STDERR && ! (-t STDOUT) || -t STDOUT && !(-t STDERR)
Run Code Online (Sandbox Code Playgroud)
或更短
-t STDOUT ^ -t STDERR # thanks to @mob
Run Code Online (Sandbox Code Playgroud)
你知道你没事。
编辑:STDERR 和 STDOUT 都是常规文件的情况的解决方案:
Tom Christianson 建议统计并比较 dev 和 ino 字段。这在 UNIX 中可以工作,但是,正如 @cjm 指出的那样,在 Windows 中不行。
如果您可以保证没有其他程序会写入该文件,则可以在 Windows 和 UNIX 中执行以下操作:
>>到非空文件。