perl遍历文件

转载 2007年09月28日 17:54:00
本贴对三种遍历文件夹方法比较。
1. 使用File::Find;
2. 递归遍历。(遍历函数为lsr)
3. 使用队列或栈遍历。(遍历函数为lsr_s)

1.use File::Find

#!/usr/bin/perl -W
#
# File: find.pl
# Author:  路小佳
# License: GPL-2

use strict;
use warnings;
use File::Find;

my ($size, $dircnt, $filecnt) = (0, 0, 0);

sub process {
    my $file = $File::Find::name;
    #print $file, "/n";
    if (-d $file) {
        $dircnt++;
    }
    else {
        $filecnt++;
        $size += -s $file;
    }
}

find(/&process, '.');
print "$filecnt files, $dircnt directory. $size bytes./n";

2. lsr递归遍历

#!/usr/bin/perl -W
#
# File: lsr.pl
# Author: 路小佳
# License: GPL-2

use strict;
use warnings;

sub lsr($) {
    sub lsr;
    my $cwd = shift;

    local *DH;
    if (!opendir(DH, $cwd)) {
        warn "Cannot opendir $cwd: $! $^E";
        return undef;
    }
    foreach (readdir(DH)) {
        if ($_ eq '.' || $_ eq '..') {
            next;
        }
        my $file = $cwd.'/'.$_;
        if (!-l $file && -d _) {
            $file .= '/';
            lsr($file);
        }
        process($file, $cwd);
    }
    closedir(DH);
}

my ($size, $dircnt, $filecnt) = (0, 0, 0);

sub process($$) {
    my $file = shift;
    #print $file, "/n";
    if (substr($file, length($file)-1, 1) eq '/') {
        $dircnt++;
    }
    else {
        $filecnt++;
        $size += -s $file;
    }
}

lsr('.');
print "$filecnt files, $dircnt directory. $size bytes./n";

3. lsr_s栈遍历

#!/usr/bin/perl -W
#
# File: lsr_s.pl
# Author: 路小佳
# License: GPL-2

use strict;
use warnings;

sub lsr_s($) {
    my $cwd = shift;
    my @dirs = ($cwd.'/');

    my ($dir, $file);
    while ($dir = pop(@dirs)) {
        local *DH;
        if (!opendir(DH, $dir)) {
            warn "Cannot opendir $dir: $! $^E";
            next;
        }
        foreach (readdir(DH)) {
            if ($_ eq '.' || $_ eq '..') {
                next;
            }
            $file = $dir.$_;         
            if (!-l $file && -d _) {
                $file .= '/';
                push(@dirs, $file);
            }
            process($file, $dir);
        }
        closedir(DH);
    }
}

my ($size, $dircnt, $filecnt) = (0, 0, 0);

sub process($$) {
    my $file = shift;
    print $file, "/n";
    if (substr($file, length($file)-1, 1) eq '/') {
        $dircnt++;
    }
    else {
        $filecnt++;
        $size += -s $file;
    }
}

lsr_s('.');
print "$filecnt files, $dircnt directory. $size bytes./n";

对我的硬盘/dev/hda6的测试结果。

1: File::Find

26881 files, 1603 directory. 9052479946 bytes.

real    0m9.140s
user    0m3.124s
sys     0m5.811s

2: lsr

26881 files, 1603 directory. 9052479946 bytes.

real    0m8.266s
user    0m2.686s
sys     0m5.405s

3: lsr_s

26881 files, 1603 directory. 9052479946 bytes.

real    0m6.532s
user    0m2.124s
sys     0m3.952s

测试时考虑到cache所以要多测几次取平均, 也不要同时打印文件名, 因为控制台是慢设备, 会形成瓶颈。
lsr_s之所以用栈而不是队列来遍历,是因为Perl的push shift pop操作是基于数组的, push pop这样成对操作可能有优化。内存和cpu占用大小顺序也是1>2>3.

                           CPU load          memory
use File::Find             97%               4540K
lsr                        95%               3760K
lsr_s                      95%               3590K

结论: 强烈推荐使用lsr_s来遍历文件夹。

=============再罗嗦几句======================
从执行效率上来看,find.pl比lsr.pl的差距主要在user上, 原因是File::Find模块选项较多, 条件判断费时较多,而lsr_s.pl比lsr.pl在作系统调用用时较少, 是因为递归时程序还在保存原有的文件句柄和函数恢复现场的信息, 所以sys费时较多。 所以lsr_s在sys与user上同时胜出是不无道理的。 

perl遍历文件夹将文件转化为utf-8格式

制作需求来源: 用eclipse打开网站源码,发现java代码中文乱码,想都不用想,文件格式肯定不是utf-8(因为以前我用notepad++看过),这次我实在是不想手动改了,就用perl处理了,搜了...

三种遍历文件夹方法比较(PERL)

一般黑客都常用遍历方法来进行插入挂马代码等。 三种遍历文件夹方法比较 本贴对三种遍历文件夹方法比较。 1. 使用File::Find; 2. 递归遍历。(遍历函数为lsr) 3. 使用队列或栈遍历。(...

文件遍历搜索工具

  • 2017年11月13日 09:09
  • 13.96MB
  • 下载

遍历文件MD5码

  • 2016年04月21日 09:38
  • 11KB
  • 下载

c++ 遍历目录下文件和文件夹

function:遍历目录下所有文件,返回文件总数,子文件夹总数(修改一下可以获得全部文件名等)。 [cpp] view plaincopy #include "stdl...

遍历删除包含某字符的文件

  • 2015年08月19日 13:39
  • 2KB
  • 下载

C#遍历指定文件夹中的所有文件

C#遍历指定文件夹中的所有文件  DirectoryInfo TheFolder=new DirectoryInfo(folderFullName); //遍历文件夹 foreach(Direc...
  • yal179
  • yal179
  • 2014年05月28日 15:41
  • 2529

MFC 文件遍历及批处理生成

  • 2015年07月21日 11:08
  • 4.81MB
  • 下载

文件件 遍历

  • 2013年06月10日 14:45
  • 1.53MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:perl遍历文件
举报原因:
原因补充:

(最多只允许输入30个字)