如何在Perl中更改系统调用的标准输出文件句柄?

时间:2009-06-13 15:53:06

标签: perl qx

我正在尝试使用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",但我想知道为什么上面的代码无效。

5 个答案:

答案 0 :(得分:3)

select函数更改输出的默认文件句柄。它不会更改STDOUT,它指向它指向的任何内容,无论它是否是输出的默认文件句柄。如果你想改变STDOUT,你必须做一些像yle​​bre或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::Open2IPC::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