使用 Perl 快速清理目录
Fast directory clean-up with Perl
我需要清理我的网络服务器上包含数百万个日志文件的目录。我找到了 this great article 如何做到这一点。然而,我很感兴趣的那一行中有一些有趣的东西。
这是我感兴趣的 Perl 代码:
for(<*>){((stat)[9]<(unlink))}
与perl -e 'code'
一起运行。
所以,这是我的问题:
for(<*>)
构造 - 我假设它遍历当前目录中的文件。但是它在哪里存储迭代器?
stat
和 unlink
函数至少需要一个参数,我假设...但是它在哪里?
- 为什么调用
(stat)[9]
的结果与调用 (unlink)
的结果进行比较?结果是什么?
抱歉,我是一个不懂 perl 的人,因此我不理解所有这些 Perl 缩写。这就是我问这个问题的原因。
谢谢!
- 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 看到它。
一条线路走很多捷径:
<*>
是菱形算子的特例。您不能访问迭代器对象,就像在其他语言中一样。在这里,它调用 glob
函数。在列表上下文中,它 return 是所有结果的列表(它们是文件的行,或者在您的情况下是目录的内容。 return 的值传递给 for
遍历列表并将 $_
中的值作为别名。$_
是许多函数的 "default variable"…
- 这把我们带到了这里。许多核心函数默认为不带参数的
$_
。 unlink
and stat
. 也是如此
(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: $!";
}
另请注意,删除文件时检查是否失败可能是谨慎的做法。
我需要清理我的网络服务器上包含数百万个日志文件的目录。我找到了 this great article 如何做到这一点。然而,我很感兴趣的那一行中有一些有趣的东西。
这是我感兴趣的 Perl 代码:
for(<*>){((stat)[9]<(unlink))}
与perl -e 'code'
一起运行。
所以,这是我的问题:
for(<*>)
构造 - 我假设它遍历当前目录中的文件。但是它在哪里存储迭代器?stat
和unlink
函数至少需要一个参数,我假设...但是它在哪里?- 为什么调用
(stat)[9]
的结果与调用(unlink)
的结果进行比较?结果是什么?
抱歉,我是一个不懂 perl 的人,因此我不理解所有这些 Perl 缩写。这就是我问这个问题的原因。
谢谢!
- 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 看到它。
一条线路走很多捷径:
<*>
是菱形算子的特例。您不能访问迭代器对象,就像在其他语言中一样。在这里,它调用glob
函数。在列表上下文中,它 return 是所有结果的列表(它们是文件的行,或者在您的情况下是目录的内容。 return 的值传递给for
遍历列表并将$_
中的值作为别名。$_
是许多函数的 "default variable"…- 这把我们带到了这里。许多核心函数默认为不带参数的
$_
。unlink
andstat
. 也是如此
(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: $!";
}
另请注意,删除文件时检查是否失败可能是谨慎的做法。