Chinaunix首页 | 论坛 | 博客
  • 博客访问: 339583
  • 博文数量: 85
  • 博客积分: 1420
  • 博客等级: 上尉
  • 技术积分: 787
  • 用 户 组: 普通用户
  • 注册时间: 2007-01-10 09:02
文章分类

全部博文(85)

文章存档

2011年(5)

2010年(51)

2009年(29)

我的朋友

分类:

2010-01-18 18:45:59

如果你具有任何UNIX方面的经验,你自然就会发现你需要用到find命令,这个命令对在整个文件系统中搜索文件名十分有用,特别是你可以使用外卡来匹配文件名并循环地穿过任何的目录结构(许可情况下)。UNIX的find命令可以对找到的文件执行其他的命令。

Perl之中的File::Find模块包含有相同的功能并给你带来编程性结构方面的优势。为了展示它的工作方式,我将给出一个使用File::Find模块的脚本实例。

简易实例

这个Perl脚本可以帮助你清理你的PC硬盘,这是通过寻找以.tmp, .chk或是.zip结尾的文件或是以~符号开始的文件来完成的(你可以在中看到整个脚本)。脚本将输出它找到的每一个文件的完整路径,而且在最后会显示出所占用的字节数。如果已经安装了Perl,你就可以在Windows或UNIX上运行这个脚本。注意在UNIX环境下,你必须修改脚本的第一行:改变/bin/perl路径来匹配环境中的Perl路径。在这个例子中,我假设你是在Windows环境下运行这个脚本。

解决方案

当然,微软公司的GUI Find也提供了这些功能中的一部分,但我还是编写了脚本。这是由于一旦你在Perl中有了这个文件,你就可以用它来做各种事,例如寻找一个特定的模式,自动地将其删除,或将其作为另一个应用程序的输出。

我在标准Perl库和Perl函数中设置了一个模块,因此当你的机器上安装了Perl之后,所有必要的模块就都可以使用了(我从获得了Perl)。File::Find函数模仿了UNIX的find命令并将穿过一个文件树。这里是此方式的API:

Find(&yoursubroutine, ‘dir1’, ‘dir2’…);

你提供的子程序,我将在后面详细叙述。还有你希望进行搜索的目录的列表,记住这些目录将以一种深度优先方式被穿过。

我使用的另一个方式就是stat()函数(与C的同名库函数类似)。它给出各种关于将文件作为一个争议对待的信息,显示了此方式的API。

这里要注意函数返回的值位于一个列表之中,唯一一个我们感兴趣的值就是$size,它包含了给定文件的大小(用字节表示)。

所有工作都会在子程序中被执行,要记住每一次遇到一个文件时,它都会被调用,所以,我们的工作就是要判定文件名是否与我们要寻找的文件相匹配。

File::Find方式具有特殊变量,将被赋予特定的信息,显示如下:

  • $_包含目录中的当前文件名
  • $File::Find::dir包含当前目录名
  • $File::Find::name包含$File::Find::dir/$_

当子程序被调用时,你就会确实位于变量$File::Find::dir的目录中。你可以在中看到,子程序使用常规表达式来与$_匹配,$_使用一个if声明来寻找我们前面详细给出的所有文件名。

如果在$_之中存储的文件名与if声 明中的五个常规表达式中的任何一个相匹配,我们就将在其下面输入代码块,常规表达式非常的简单,“.”代表一个文字上的点号而不是常规表达式中的“.”的 特殊意义。我们使用“”符号来避开特殊意义。“$”代表一个字符串最后的匹配而“^”代表与开头匹配。表A显示了我们试图将其与相对应的常规表达式相匹配 的文件。

File that ends with .zip

/.zip$/

File that ends with .tmp

/.tmp$/

File that ends with .TMP

/.TMP$/

File that begins with ~

/^~/

File that ends with .chk

/.chk/

这里要注意的是脚本对小写的tmp和大写的TMP同时进行查找,而出于效率方面的考虑,你可以将文件名改为大写并只查找TMP匹配。

最后,脚本使用stat()函数来记录所有与if声明之中的某个条件相匹配的文件所使用的字节数。如果条件符合,脚本将存储$size之中的值并将其加入到$ByteCount记录变量,如下面的代码所示:

$ByteCount += $size;

要在你的机器上运行脚本,在DOS命令提示窗口下键入下面的命令:

Perl diskrpt.pl

这里假设了你已经修改了你的PATH变量来包括可执行程序,且你已经将utility存储在名为Diskrpt.pl的文件之中。命令的输出将在DOS命令提示窗口中出现。

在后面的文章中,我将介绍到脚本的修改,例如删除某个文件类型或将结果交于另一个应用程序。

perl下的File::Find模块具有shell下的find命令的功能,下面具体看2个例子:

1,找出某个目录下面以*.old结尾的文件

#!/usr/bin/perl -w

use strict;
use File::Find;

my $path = '/home/test/';
sub wanted {
    if ( -f $File::Find::name ) {
        if ( $File::Find::name =~ /\.old$/ ) {
            print "$File::Find::name\n";

        }
    }

}

find( \&wanted, $path );


2,找出某个目录下面几天前的文件

my $path = '/home/test/';
opendir DH, $path or die "cannot chdir to $path : $!";

for my $file (readdir DH) {
    next if $file eq "." or $file eq "..";
    next if $file =~ /^\./;
    if (time() - (stat($path.$file))[8] > (60*60*24*7)) {
        print $path.$file."\n";
    }
}
closedir DH;
阅读(7956) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~