Sharing

2013年6月10日 星期一

File::Find in Perl

最近在寫一個小程式要處理檔案, 所以需要工具把一個 folder 下的檔案列出來,整理一下有試過的方法

readdir

http://perlmeme.org/faqs/file_io/directory_listing.html
這種方法的缺點是,

  • 會列出  "." 和 ".." 
  • 要自己區分 folder & file
  • 沒有辦法加 Filter
  • 沒有按照字母順序

#!/usr/bin/perl
use strict;
use warnings;

my $directory = '/tmp';

opendir (DIR, $directory) or die $!;

while (my $file = readdir(DIR)) {
    print "$file\n";
}

closedir(DIR);

Glob

http://perldoc.perl.org/functions/glob.html

語法很簡單, 而且回傳有按照字母順序,也可以做簡單的 filter, 不過遇到複雜一點的 case, 可能就不夠用

@filelist = glob "/usr/lib/perl/*.pl";

File::Find

這個方案就強大的多, 要做什麼事幾乎都做的到,因為 filter function 是自己寫,
也有 find2perl 這個工具幫你產生 code. 但壞處就是什麼都要自己刻

use File::Find;
find(\&wanted, @directories_to_search);
sub wanted { ... }

File::Find::Rule

http://search.cpan.org/~rclamp/File-Find-Rule-0.33/lib/File/Find/Rule.pm
這個是 File::Find 的改良版,他提供不少小工具來幫助你做 filter, 幾乎和 Linux 裡 find 功能差不多,不過他仍然有一些限制
  • 沒有按照字母順序,必須自己用 sort 排序
  • modified, accessed, changed 這三個理論上應該要回傳天數,但在這邊只回傳 Boolean 值

實作 find -type f -name "*.pl" -mtime +3 -maxdepth 1
my $rule =  File::Find::Rule->new;
$rule->file;
$rule->maxdepth(1);
$rule->name("*.pl");
$rule->exec( sub { -M $_ > 3});
my @fid_files = sort { $a cmp $b } $rule->in($curr_path);

File Operation in Perl

再復習一下 File 的一些基本操作
https://metacpan.org/module/perlfunc#Alphabetical-Listing-of-Perl-Functions

Find in Bash Shell

也復習一下 Find 的操作

http://www.gnu.org/software/findutils/manual/html_mono/find.html

-mtime n

    Numeric arguments can be specified as

       +n     for greater than n,

       -n     for less than n,

       n      for exactly n.


# find the files modified in 30 days.
$ find . -iname "*.c" -mtime -30 -type f

# find the files modified over 30 days.
$ find . -iname "*.c" -mtime +30 -type f

# find the files modified between 20-30 days ago.
$ find . -mtime -30 -mtime +20 -type f

# find the files modified in 30 days, but the based time is 00:00:00 today, not current time.
$ find . -daystart -mtime 0 -type f

# find the files modified between 2012-01-01 and 2013-01-01
$ touch --date "2012-01-01" /tmp/start
$ touch --date "2013-01-01" /tmp/end
$ find . -type f -newer /tmp/start -not -newer /tmp/end


http://www.cyberciti.biz/faq/linux-unix-osxfind-files-by-date/

http://blog.miniasp.com/post/2010/08/27/Linux-find-command-tips-and-notice.aspx

http://www.electrictoolbox.com/using-find-to-locate-files-modified-in-the-last-24-hours/




沒有留言: