加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

遍历文件夹的方法比较

发布时间:2020-12-16 00:11:51 所属栏目:大数据 来源:网络整理
导读:本贴对三种遍历文件夹方法比较。 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 Fil
本贴对三种遍历文件夹方法比较。
1. 使用File::Find;
2. 递归遍历。(遍历函数为lsr)
3. 使用队列或栈遍历。(遍历函数为lsr_s)

1.use File::Find
  1. #!/usr/bin/perl -W
  2. #
  3. # File: find.pl
  4. # Author: 路小佳
  5. # License: GPL-2

  6. use strict;
  7. use warnings;
  8. use File::Find;

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

  10. sub process {
  11. my $file = $File::Find::name;
  12. #print $file,"n";
  13. if (-d $file) {
  14. $dircnt++;
  15. }
  16. else {
  17. $filecnt++;
  18. $size += -s $file;
  19. }
  20. }

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


2. lsr递归遍历
  1. #!/usr/bin/perl -W
  2. #
  3. # File: lsr.pl
  4. # Author: 路小佳
  5. # License: GPL-2

  6. use strict;
  7. use warnings;

  8. sub lsr($) {
  9. sub lsr;
  10. my $cwd = shift;

  11. local *DH;
  12. if (!opendir(DH,$cwd)) {
  13. warn "Cannot opendir $cwd: $! $^E";
  14. return undef;
  15. }
  16. foreach (readdir(DH)) {
  17. if ($_ eq '.' || $_ eq '..') {
  18. next;
  19. }
  20. my $file = $cwd.'/'.$_;
  21. if (!-l $file && -d _) {
  22. $file .= '/';
  23. lsr($file);
  24. }
  25. process($file,$cwd);
  26. }
  27. closedir(DH);
  28. }

  29. my ($size,0);

  30. sub process($$) {
  31. my $file = shift;
  32. #print $file,"n";
  33. if (substr($file,length($file)-1,1) eq '/') {
  34. $dircnt++;
  35. }
  36. else {
  37. $filecnt++;
  38. $size += -s $file;
  39. }
  40. }

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


3. lsr_s栈遍历
  1. #!/usr/bin/perl -W
  2. #
  3. # File: lsr_s.pl
  4. # Author: 路小佳
  5. # License: GPL-2

  6. use strict;
  7. use warnings;

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

  11. my ($dir,$file);
  12. while ($dir = pop(@dirs)) {
  13. local *DH;
  14. if (!opendir(DH,$dir)) {
  15. warn "Cannot opendir $dir: $! $^E";
  16. next;
  17. }
  18. foreach (readdir(DH)) {
  19. if ($_ eq '.' || $_ eq '..') {
  20. next;
  21. }
  22. $file = $dir.$_;
  23. if (!-l $file && -d _) {
  24. $file .= '/';
  25. push(@dirs,$file);
  26. }
  27. process($file,$dir);
  28. }
  29. closedir(DH);
  30. }
  31. }

  32. my ($size,0);

  33. sub process($$) {
  34. my $file = shift;
  35. print $file,1) eq '/') {
  36. $dircnt++;
  37. }
  38. else {
  39. $filecnt++;
  40. $size += -s $file;
  41. }
  42. }

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



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

1: File::Find
  1. 26881 files,1603 directory. 9052479946 bytes.

  2. real 0m9.140s
  3. user 0m3.124s
  4. sys 0m5.811s
复制代码


2: lsr
  1. 26881 files,1603 directory. 9052479946 bytes.

  2. real 0m8.266s
  3. user 0m2.686s
  4. sys 0m5.405s
复制代码


3: lsr_s
  1. 26881 files,1603 directory. 9052479946 bytes.

  2. real 0m6.532s
  3. user 0m2.124s
  4. sys 0m3.952s
复制代码

测试时考虑到cache所以要多测几次取平均,也不要同时打印文件名, 因为控制台是慢设备, 会形成瓶颈。
lsr_s之所以用栈而不是队列来遍历,是因为Perl的push shift pop操作是基于数组的, push pop这样成对操作可能有优化。内存和cpu占用大小顺序也是1>2>3.
  1. CPU load memory
  2. use File::Find 97% 4540K
  3. lsr 95% 3760K
  4. lsr_s 95% 3590K
复制代码
结论: 强烈推荐使用lsr_s来遍历文件夹。 =============再罗嗦几句====================== 从执行效率上来看,find.pl比lsr.pl的差距主要在user上, 原因是File::Find模块选项较多, 条件判断费时较多,而lsr_s.pl比lsr.pl在作系统调用用时较少, 是因为递归时程序还在保存原有的文件句柄和函数恢复现场的信息, 所以sys费时较多。 所以lsr_s在sys与user上同时胜出是不无道理的。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读