ikegami,
I am a little confused about what you are saying
File handles opened using open FILE, ">", \$var don't have file descriptors since there are no corresponding OS file handles. Since open FILE2, ">&FILE" means open a new file from the file descriptor of "FILE", it's no suprise it doesn't work. The code below demonstrates this and a fix.
It seems to apply only for opening file handles to strings instead of files.
The difference is shown in the output below (then followed by the code that generated it)
>perl out.pl d.d
initial: fileno(*STDOUT) = 1
initial: fileno(*STDERR) = 2
redirected: fileno(*STDOUT) = 1
redirected: fileno(*STDERR) = 2
hello - this is contents of d.d
testing stdout capture 1
testing stderr capture
testing stdout capture 2
>perl out.pl
initial: fileno(*STDOUT) = 1
initial: fileno(*STDERR) = 2
redirected: fileno(*STDOUT) = -1
redirected: fileno(*STDERR) = -1
hello - this is $captured_output
testing stdout capture 1
testing stdout capture 2
Example code below:
#!/usr/bin/perl
use strict;
use FileHandle;
my $use_file = shift;
local *SAVED_STDOUT;
local *SAVED_STDERR;
open SAVED_STDOUT, ">&STDOUT"
or die "couldn't save STDOUT: $!\n";
open SAVED_STDERR, ">&STDERR"
or die "couldn't save STDERR: $!\n";
printf("\ninitial: fileno(*STDOUT) = %d\n",
fileno(*STDOUT)); # 1
printf("initial: fileno(*STDERR) = %d\n",
fileno(*STDERR)); # 2
my $captured_output = "";
# redirect standard out to file or string, as requested
close STDOUT;
if ($use_file) {
open STDOUT, ">", "$use_file"
or die "couldn't re-open STDOUT: $!\n";
}
else {
open STDOUT, ">", \$captured_output
or die "couldn't re-open STDOUT: $!\n";
}
close STDERR;
open STDERR, ">&STDOUT"
or die "couldn't re-open STDERR: $!\n";
printf SAVED_STDOUT "\nredirected: fileno(*STDOUT) = %d\n",
fileno(*STDOUT); # 1
printf SAVED_STDOUT "redirected: fileno(*STDERR) = %d\n",
fileno(*STDERR); # 2
select STDOUT; $|++;
select STDERR; $|++;
select STDOUT;
print STDOUT "testing stdout capture 1\n";
print STDERR "testing stderr capture\n";
print STDOUT "testing stdout capture 2\n";
close STDOUT; open STDOUT, ">&SAVED_STDOUT";
close STDERR; open STDERR, ">&SAVED_STDERR";
if ($use_file) {
printf SAVED_STDOUT
"\n\nhello - this is contents of $use_file\n\n";
system("cat $use_file");
}
else {
printf "hello - this is \$captured_output\n\n";
printf STDERR $captured_output, "\n";
}
update adjusted indentation of code, but no changes to code