【问题标题】:Calling subroutine with system command inside the another script在另一个脚本中使用系统命令调用子程序
【发布时间】:2014-06-16 12:50:21
【问题描述】:

我在 Windows 7 x86 下运行 perl,当我调用从另一个脚本执行外部命令的子例程时出现错误。

我有两个脚本,script1 有一个执行程序 (patt.exe) 的子例程,script2 通过require 使用这个子例程。

当我运行 script1 时,它可以正常工作。但是当我尝试从 script2 内部使用这个子例程时,我得到了以下错误。

错误:

'patt.exe' is not recognized as an internal or external command, operable program or batch file.

脚本1

#patt('file.txt');
sub patt { 
my $filename=shift@;
system("cmd.exe /c patt.exe -S $filename");
}
1;

脚本2

require 'sub-directory/script1.pl';
patt('file.txt');

我应该提到 script1patt.exe 位于子目录(require 'sub-directory/script1.pl';)中,当我将所有文件放在同一目录中时(@987654327 @) 一切正常。如果我使用qx 或者当我将参数作为数组传递给脚本时,这个问题仍然存在。

如果有人能帮助我,我将非常感激。

【问题讨论】:

  • -f "patt.exe" or die "must be in some other folder"; 就在system 通话之前
  • @mpapec,当我将脚本和 .exe 文件放在同一目录中时,它可以正常工作。目前“script1”和“patt.exe”位于 sub_directory 和 script2 中,我提到“需要 'sub_directory/script1.pl';”。什么可能是错的?!无论如何我可以将带有子例程脚本的 .exe 文件放在单独的文件夹中吗?
  • 这是windows问题;使用完整的 .exe 路径或将其放入系统 PATH。

标签: windows perl exe


【解决方案1】:

一种解决方案是您可以将当前工作目录更改为外部程序的工作目录。为此,您可以使用与您的程序共享同一目录的 perl 脚本的 __FILE__ 变量。

当然,需要注意的一件事是,如果您使用此解决方案,您可能需要提供到您的 $filename 的完全限定路径:

use strict;
use warnings;

use Cwd;
use File::Spec;

sub patt {
    my $filename = shift;

    # Temporarily change cwd
    my $oldcwd = cwd;
    my ($vol, $path) = File::Spec->splitpath(__FILE__);
    chdir($path);

    # Execute program.  Note that $filename will likely need to be a fully qualified path
    system("patt.exe -S $filename");

    # Revert cwd
    chdir($oldcwd);
}

1;

【讨论】:

  • 感谢@Miller,您的解决方案效果很好。我已将 my ($vol, $path) = File::Spec->splitpath(__FILE__); 替换为 my $path=__FILE__; $path=~ s/\/.+?\.pl//; 并且一切正常。
【解决方案2】:

首先,您无需通过cmd.exe 致电pratt.exe。你应该可以这样做:

system "patt.exe -S $filename";

错误来自系统命令无法找到命令patt.exe 以执行它。试试这个:

 warn "WARN: \@INC: " . join "\n ", $ENV{PATH};

这将打印出所有搜索可执行文件的目录。通常在 Windows 中,当前目录$PATH 中的最后一个条目。我不是 100% 确定 require 与当前工作目录的关系如何。例如,当您将子例程放在另一个目录的文件中时,它可能无法在当前目录中找到pratt.exe,因为当前目录现在是子例程所在的位置。

所以,您可能想做的另一件事是使用Cwd 导入cad 命令:

use strict;     # Always! This will help point to errors.
use warnings;   # Always! This will help point to errors.
use Cwd;

sub patt { 
    my $filename = shift;

    warn "Current Working Directory is: " . cwd;
    warn "PATH is: " . join "\n", $ENV{PATH};

    my $error = system("cmd.exe /c patt.exe -S $filename");
    if ( $error ) {
       die qq(Patt failed.);
    }
}
1;

对照 Windows PATH 检查当前工作目录,看看是否能提示您为什么 patt 没有被执行。

【讨论】:

  • 谢谢。可执行文件不在我的系统路径中,我不想(我在主工作 PC 中没有权限)设置它。我很清楚,第二个脚本在调用第一个脚本时会在其目录中运行所有子例程,而不是在 script1 子目录中。在这些条件下,.exe 文件必须在 script2 目录中。我有很多 .exe 文件,想将它们排列在子目录而不是主目录中。
  • 然后,您必须在系统调用中包含可执行文件的目录名称。您可以尝试:更改 $ENV{PATH} 变量本身以包含所需的目录。你可以在 Unix 上做到这一点,它会保持,但我不知道这是否适用于 Windows。附加您的目录,看看您是否可以访问您的可执行文件。在 Unix 上,PATH 会在程序退出后重置。
猜你喜欢
  • 1970-01-01
  • 2021-11-24
  • 2022-01-18
  • 2013-04-04
  • 1970-01-01
  • 1970-01-01
  • 2015-08-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多