Perl Glob奇怪的行为 [英] Perl glob strange behaviour

查看:44
本文介绍了Perl Glob奇怪的行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一段perl代码:

I have a piece of perl code:

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归档文件匹配项有所不同,即使它为空,它也会返回非空结果.

sometimes the if returns true but the zip would not match anything, why would that happen? There is no concurrent processes that would remove files in the meantime, it's just glob is returning something different from zip archive match for files, it returns non-empty result even though it should be empty.

推荐答案

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

The glob function in scalar context becomes an iterator, not a test for file existence! This can be demonstrated by the following code:

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会记住给定的 first 模式,然后对所有匹配项进行迭代,但是在迭代器耗尽之前,不要使用它给出的任何新模式.因此,在表达式glob("$data_dir/*$archivefrom*")中,无法识别$data_dir$archivefrom变量中的更新值.在所有可能的结尾,您还将获得一个undef返回值.那么if分支显然没有执行.

That is, glob remembers the first pattern it was given, then iterates over all matches, but not use any new patterns it was given until the iterator is exhausted. Therefore in your expression glob("$data_dir/*$archivefrom*"), updated values in the $data_dir and $archivefrom variables are not recognized. You will also get one undef return value at the end of all possibilities. Then the if branch obviously isn't executed.

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

To test if at least one file matching your pattern exists, you have to fetch all matches at once, thus avoiding the iteration. Use list context for that. We could use the pseudoperator ()= to count the number of matches – anything ≥ 1 is fine. We can also assign the first match to a variable, and use it in your system command, to avoid shell interpolation issues:

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;
}

这篇关于Perl Glob奇怪的行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆