使用 Perl 快速清理目录

Fast directory clean-up with Perl

我需要清理我的网络服务器上包含数百万个日志文件的目录。我找到了 this great article 如何做到这一点。然而,我很感兴趣的那一行中有一些有趣的东西。

这是我感兴趣的 Perl 代码:

for(<*>){((stat)[9]<(unlink))}

perl -e 'code'一起运行。

所以,这是我的问题:

  1. for(<*>) 构造 - 我假设它遍历当前目录中的文件。但是它在哪里存储迭代器?
  2. statunlink 函数至少需要一个参数,我假设...但是它在哪里?
  3. 为什么调用 (stat)[9] 的结果与调用 (unlink) 的结果进行比较?结果是什么?

抱歉,我是一个不懂 perl 的人,因此我不理解所有这些 Perl 缩写。这就是我问这个问题的原因。

谢谢!

  1. the for(<*>) construction - I assume it iterates through the files in the current directory. But where does it store the iterator?

for 循环可用于遍历 arrays/lists,因此如果 <*> 生成一个列表,那么您的代码只是一个 运行 的 for 循环。事实证明 <*> 是拼写 glob() 的另一种方式,它有点像用于检索文件名的正则表达式,而 glob() returns 是 list context[ 中的一个列表=21=]--这是for循环提供的上下文。参见:http://perldoc.perl.org/functions/glob.html.

请注意,单引号会阻止 shell 扩展 *,这会阻止 perl 看到它。

一条线路走很多捷径:

  1. <*>是菱形算子的特例。您不能访问迭代器对象,就像在其他语言中一样。在这里,它调用 glob 函数。在列表上下文中,它 return 是所有结果的列表(它们是文件的行,或者在您的情况下是目录的内容。 return 的值传递给 for 遍历列表并将 $_ 中的值作为别名。$_ 是许多函数的 "default variable"…
  2. 这把我们带到了这里。许多核心函数默认为不带参数的 $_unlink and stat.
  3. 也是如此
  4. (stat)[9] 表示在列表上下文中执行 stat 并且 select 第 10 个结果(索引从零开始,这是修改时间)。 (将其与 $foo[9] 之类的数组访问进行比较)。

密码

for(<*>){((stat)[9]<(unlink))}

相当于:

for my $file (<*>) {
    my $mtime = (stat($file))[9];
    $mtime < unlink($file);
}

<*> 也可以用 glob "*" 替换,这可能更具可读性。

该代码将删除当前目录中的所有文件。它不会删除目录。

请注意,循环中的最后一条语句完全是多余的。如果use warnings生效,会给出警告:

Useless use of numeric lt (<) in void context

为了使这段代码有意义,我希望进行真正重要的比较,例如将 $mtime 与某个时间进行比较以了解哪些日志是旧的,例如:

if ($mtime < $oldtime) {
    unlink $file or die "Cannot unlink $file: $!";
}

另请注意,删除文件时检查是否失败可能是谨慎的做法。