How to I print to STDERR only if STDOUT is a different destination?

io, perl, stderr, stdout, unix

Solution

On Unix-style systems, you should be able to do:

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]));

But that won't work on Windows, which doesn't have real inode numbers. It gives both false positives (thinks they're different when they aren't) and false negatives (thinks they're the same when they aren't).

Problem

I would like Perl to write to STDERR only if STDOUT is not the same. For example, if both STDOUT and STDERR would redirect output to the Terminal, then I don't want STDERR to be printed. Consider the following example (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 ``` Now consider this (this is what I would like to achieve): ``` bash $ outerr.pl Hello standard output! ``` However, if I redirect out to a file, I'd like to get: ``` bash $ outerr.pl > /dev/null Hello standard error ``` and similary the other way round: ``` bash $ outerr.pl 2> /dev/null Hello standard output! ``` If I re-direct both out/err to the same file, then only out should be displayed: ``` bash $ outerr.pl > foo.txt 2>&1 bash $ cat foo.txt Hello standard output! ``` So is there a way to evaluate / determine whether OUT and ERR and are pointing to the same “thing” (descriptor?)?

Original source