我正在尝试使用select更改系统函数的stdout。但它似乎没有奏效。系统输出将显示在控制台上,而不是重定向到文件。
use strict;
use warnings;
chdir "C:\\Documents and Settings\\" or die "cannot open the dir\n";
open FH, ">out.txt" or die "cannot open out.txt\n";
select FH or die " cannot change the stdout\n";
system "dir /a" ;
虽然我可以system "dir /a > out.txt"
,但我想知道为什么上面的代码无效。
答案 0 :(得分:3)
select
函数更改输出的默认文件句柄。它不会更改STDOUT,它指向它指向的任何内容,无论它是否是输出的默认文件句柄。如果你想改变STDOUT,你必须做一些像ylebre或Jon的回答。
启动子进程时,它获得与父进程相同的标准输出。它并不关心父项的默认文件句柄是什么。
答案 1 :(得分:2)
您的代码存在的问题是system
命令无法为您捕获输出。您可以使用qx//
:
use strict;
use warnings;
open my $fh, ">", "output.txt" or die $!;
my $oldfh= select $fh;
print qx/ls -a/;
select $oldfh;
close $fh or warn $!;
还有其他选项可以运行外部应用程序并获取其输出,例如IPC::Open2
和IPC::Open3
模块。它们默认包含在perl中。
旁注:不要使用globs作为文件句柄:它们是全局变量,而全局变量是邪恶的。请改用词法变量(FH
与$fh
)。此外,您应该使用三个参数open
而不是两个参数,因为前者比后者更安全。
答案 2 :(得分:1)
在这种情况下,我不确定'select'是你在寻找什么。要将STDOUT重定向到文件,您可以执行以下操作:
use strict;
use warnings;
use IO::Handle;
open FH, "> out.txt";
STDOUT->fdopen( \*FH, 'w' ) or die $!;
print "Hello world!\n";
system "dir /a";
希望这有帮助!
答案 3 :(得分:1)
也许this有帮助
答案 4 :(得分:-2)
我在系统(而不是Perl)级别重新分配文件描述符:
sub reopen($$$) {
open $_[0], $_[1]. '&='. fileno($_[2]) or die "failed to reopen: $!";
}
reopen *STDOUT, '>', $new_stdout_handle;
现在你分叉的任何东西都会认为$ new_stdout_handle是标准输出。
我在gist上贴了一个完整的例子:http://gist.github.com/129407