我正在尝试从Perl调用外部程序,即unrar,并允许在运行时将其输出打印到屏幕上。
@lin1=`cd "$wholepath_dir" & $laufwerk & unrar x -v -y "$_" ` if ($^O =~ /Win/) ;
@lin1=`cd "$wholepath_dir"; unrar x -v -y "$_" ` if (not ($^O =~ /Win/)) ;
此代码在目录内解压缩some-rar-file.rar。 但是,它没有显示任何进展。 如果它能实时显示unrar输出,而又正在进行unraring,而不是将unrar结果提供给数组,那就很好了。
对Windows和Linux都知道如何做到这一点?
答案 0 :(得分:1)
只显示进度然后忘记它,除了任何错误,对我来说终于没问题了,我通过以下方式解决了它,但仅适用于 Windows :
PreferredSize(
preferredSize: Size.fromHeight(72),
child: AppBar(
title: Text(title, style: TextStyles.h1),
centerTitle: false,
elevation: 0,
brightness: Brightness.light,
backwardsCompatibility: false,
bottom: bottomAppBarWidget,
))
这会打开一个子shell,因此会弹出另一个cmd.exe,显示整个解压缩过程,如果运行正常则立即关闭或再暂停3秒,如果出现问题,则将错误消息写入“锁定文件”。 稍后检查锁定文件的大小,以便主程序知道是否发生了错误。然后,锁文件被删除。
我想 Linux 没有这样的解决方案吗?
答案 1 :(得分:0)
这应该做到这一点:它可以让Shell处理STDERR的重定向。我没有Windows,所以不知道cmd.exe
中的相应位。
#!/usr/bin/perl
use strict;
use warnings;
sub run_command(\@$) {
my($log, $cmd) = @_;
my($redirect_start, $redirect_end);
if ($^O =~ /Win/) {
# @TODO
$redirect_start = '???';
$redirect_end = '???';
} else {
$redirect_start = '(';
$redirect_end = ') 2>&1';
}
open(my $fh, "${redirect_start}${cmd}${redirect_end} |")
or die "ERROR: $!\n";
while (<$fh>) {
push(@{ $log }, $_);
print;
}
close($fh)
or die "ERROR: $!\n";
}
my @log;
run_command(@log, 'ls dummy.*');
run_command(@log, 'ls -lht dummy.txt');
print "\nLOG:\n";
print foreach (@log);
exit 0;
我的机器的输出示例:
$ perl dummy.pl
dummy.c
dummy.c~
...
dummy.txt
dummy.txt~
dummy.xml
-rw-rw-r--. 1 USER USER 926 Jan 25 23:33 dummy.txt
LOG:
dummy.c
dummy.c~
...
dummy.txt
dummy.txt~
dummy.xml
-rw-rw-r--. 1 USER USER 926 Jan 25 23:33 dummy.txt
如果上述解决方案不能令人满意,我建议您调查IPC::Open3。
答案 2 :(得分:0)
对于像这样的交互式内容,IPC::Run
通常是个不错的选择。
use warnings;
use strict;
use IPC::Run qw/ run new_chunker /;
my @cmd = ('yourcommand', 'arg1', 'arg2');
my (@out,@err);
run \@cmd, '>', new_chunker("\n"), sub {
my $line = shift;
print $line;
push @out, $line;
}, '2>', new_chunker("\n"), sub {
my $line = shift;
print STDERR $line;
push @err, $line;
} or die $?;
答案 3 :(得分:0)
首先,请注意,用引号引起来的内容不是保护它免受外壳解析的有效方法,因为它本身可能包含引号。最好的方法是通过使用open / system / open3 / etc的列表形式来完全避免shell解析,但是由于使用的是shell元字符&
,因此无法执行此操作。因此,您可以使用String::ShellQuote为适当的外壳提供一个用引号引起来的字符串。
使用IPC::Open3:
use strict;
use warnings;
use IPC::Open3;
use String::ShellQuote;
my $quoted_dir = shell_quote $wholepath_dir;
my $quoted_file = shell_quote $_;
my $cmd = $^O =~ /Win/
? "cd $quoted_dir & $laufwerk & unrar x -v -y $quoted_file"
: "cd $quoted_dir; unrar x -v -y $quoted_file";
my $pid = open3 undef, my $stdout, '>&STDERR', $cmd;
my @lines;
while (my $line = readline $stdout) {
print $line;
push @lines, $line;
}
waitpid $pid, 0;
my $exit_code = $? >> 8;
# you can now act on the $exit_code and the @lines of STDOUT