3

我有一段 perl 代码:

if (glob("$data_dir/*$archivefrom*")) {
    my $command1 = "zip -r -T -m $backup_dir/$archivefrom.zip $data_dir/*$archivefrom*";

    my $err_cmd1 =system("$command1");
    if ($err_cmd1 != 0){print "Error $command1\n";exit 1;}
}

有时 if 返回 true 但 zip 不匹配任何内容,为什么会发生这种情况?同时没有并发进程会删除文件,它只是 glob 返回的东西与文件的 zip 存档匹配不同,即使它应该为空,它也会返回非空结果。

4

1 回答 1

6

标量上下文中的glob函数成为迭代器,而不是文件存在的测试!这可以通过以下代码来证明:

use feature 'say';
my @patterns = ('{1,2,3}', 'a', 'b', 'c');
for my $pattern (@patterns) {
  my $item = glob $pattern;
  say $item // "<undef>";
}

输出:

1
2
3
<undef>

也就是说,glob记住它给出的第一个模式,然后迭代所有匹配项,但在迭代器耗尽之前不要使用它给出的任何新模式。因此,在您的表达式中,无法识别和变量中glob("$data_dir/*$archivefrom*")的更新值。在所有可能性结束时,您还将获得一个返回值。那么分支显然没有被执行。$data_dir$archivefromundefif

要测试是否存在至少一个与您的模式匹配的文件,您必须一次获取所有匹配项,从而避免迭代。为此使用列表上下文。我们可以使用伪()=算子来计算匹配的数量——任何 ≥ 1 都可以。我们还可以将第一个匹配项分配给一个变量,并在您的system命令中使用它,以避免 shell 插值问题:

use autodie ':system'; # automatic error handling, additionally requires IPC::System::Simple

if (my ($archivePath) = glob "$data_dir/*$archiveFrom*") {
  system 'zip', '-r', '-T', '-m', "$backup_dir/$archivefrom.zip", $archivePath;
}
于 2013-09-03T21:35:39.067 回答