Perl小技巧:文件操作


*找到具有指定特征的文件*

引用:
$path = "/path/to/dir/";
opendir DIR, $path;
@arr1 = readdir DIR;
@arr2 = grep{-T "$path$_"} @arr1; #text files only
@arr3 = grep{!-d "$path$_"} @arr1; #no directories
@arr4 = grep{-s "$path$_" < 1024} @arr1; #less than 1K
代码解释:假如被测试的目录项是一个文本文件,那么 -T 文件操作符就会返回真。其实针对目录项的测试操作还有很多。(注:文件和目录在 系统 中都是以目录项的形式来管理的,所以要区别一个目录项指向的是一个文件还是一个目录需要相应的操作符)。注意上面的 readdir 函数返回指定目录下的所有目录项。因为在 grep 函数中对目录项的测试需要文件的完全路径,所以我们把 $PATH(存储了目录项的部分路径) 和 $_(存储了目录项的名字)中的内容联合起来得到文件的完全路径 *对目录进行递归搜索*
复制内容到剪贴板
代码:
use File::Find;

find(/&handleFind, 'imac:documents:code');

sub handleFind{
    my $foundFile = $File::Find::name;
    print "$foundFile/n" if ($foundFile =~ //.html?$/i);
}
RESULT: imac:documents:code:index.html imac:documents:code:perl:example.HTM 运行结果:代码讨论:那些工作于 Unix 系统的 Perl 程序员可以非常简便的利用 UNIX 上提供的工具来完成许多日常的工作,比如递归的列出指定目录下的所有目录项(也就是列出指定目录及指定目录子目录下的所有目录项目)。然而 Perl 的一个最大的特征就是可以运行于很多的平台上。所以如果你碰巧工作在一个非 UNIX 的平台,或者如果你虽工作在 UNIX 平台,但不喜欢使用系统工具写脚本,你可以选择 Perl。要完成这些巧妙的工作,你需要使用 perl 中的 File:Find 模块。当你加载了这个模块的时候,你就可以使用其中的 find 子函数,在调用这个函数的时候,需要带参数:第一个参数是一个函数的引用,这个函数由你自己建立,每次一个文件被找到的时候,它都会运行。接下来的一个参数是一串你想要搜索的路径。我写的这个示例脚本是运行在 Macintosh OS 8.x 系统上的,所以我使用了 Mac 系统的路径分隔符:。如果是在 Windows ,你可以用反斜杠,如果是在 Unix 系统则是正斜杠(至于在 Amiga 系统上用什么我就不知道了)。总之,find 函数将会在每次找到一个文件的时候调用你给出的子函数,而且会对子目录进行查找。在我的 handledfind 子函数中,我通过这个模块特定变量 $File::Find::name 来获得每次 find 找到的文件名。然后,就可以对该文件执行任何你想的测试,在上面的例子中,我们输出有 .html 的扩展名文件名。 *文件读操作* *一次读入整个文件内容。*
复制内容到剪贴板
代码:
open FH, "< anthem";
$/ = undef;
$slurp = ;
print $slurp;
运行结果:一下就显示了所有的文件内容,此刻你应该非常的自豪。:) 代码讨论:尖括号 <> 对文件句柄进行操作,在标量上下文中它将返回文件的下一条记录,在数组上下文中它将返回所有的记录。在默认的情况下,文件中的记录被认为是由换行符分开(例如回车或其他代表新行开始的字符)。你可以重新设定这个默认的分隔符,然后 Perl 将会以你指定的分隔符为准来替代换行符。全局变量 $/ 里存储了输入文件的分隔符,如果你把 $/ 的值设置为 undef ,那么 Perl 将会认为整个文件是一条记录(因为此刻已经没有文件分隔符了)。牢记 $/ 是全局变量,千万不要在脚本的其他地方不经意的改变它,这个错误将很难被发现。你可能会问,我们能否不改变 $/,而采用把文件的所有记录读到一个数组中,然后把数组联合成一个很长的字符串(比如 $slurp = join("",);)的方法实现一次读入文件。当然这也是一个有效的解决办法,但是你会发现它很慢,是否选用它取决你的应用,取决于你是否关心运行速度。 *赋值* *把一个文件句柄赋给另一个文件句柄*
复制内容到剪贴板
代码:
open(MYOUT, "> bottle.txt");
*STDOUT = *MYOUT;
print "message";
运行结果:文本文件 bottle.txt 现在包含 message 字符串。代码讨论:以前可能你配合使用过 Print 函数和文件句柄,但是你是否知道就算你没有使用文件句柄,Perl 也默认你在使用一个称为 STDOUT 的句柄?C 程序员知道 STDOUT 代表标准输出,也就是通常的屏幕,或终端窗口(或者是 CGI 程序的输出端- 浏览器 )。在这里我们完成的工作是创建我们自己的文件句柄,它指向一个给定的文件,然后我们做了一件比较鬼的工作,使用 * 前缀把 STDOUT 转换为 typeglob 类型。Typeglob 类型的数据可以有别名,这样一个变量可能会指向另一个其他名字的变量。上面第二行代码使 STDOUT 指向 MYOUT 变量。所以执行 print 操作时的默认输出对象也就成为了我们创建的文件句柄。 *同时向两个文件句柄执行写操作*
复制内容到剪贴板
代码:
use IO::Tee;
$tee = IO::Tee->new(">> debuglog.txt", /*STDOUT);
print $tee "an error ocurred on ".scalar(localtime)."/n";
运行结果:an error ocurred on Fri Feb 23 21:44:20 2001 代码讨论:如果,由于种种原因你想要同时向两个位置写入同一个字符串,这和 UNIX 下的 tee 工具的用途一样。即使你不是工作在 Unix 平台上,Perl 也通过 Tee 模块为你提供这个功能。Tee 模块可以在 CPAN 下载,你应该把它安装到 Perl 的 IO 库文件夹中。Tee 模块以 OOP 方式编写,所以使用它之前你应该首先使用它的 new 方法来创建一个 Tee 对象,整个过程需要两个参数,每个参数既可以是代表文件句柄的字符串,也可以是一个对已打开的文件句柄的引用。在上面的例子中,我们用一个字符串来代表一个以附加模式打开的文件句柄,它指向名为 debuglog.txt 的文件,另一个参数是系统内置的文件句柄 STDOUT,整个句柄是系统自动创建的,print 函数默认情况对它进行操作。为了得到一个文件句柄的引用我们需要对一个 typeglob 类型的数据使用反斜杠。Typeglob 可以代表任何已命名的某个变量,不论它是数组,散列还是标量等。使用 * 很有必要,因为文件句柄自己没有前缀符号。new 操作符返回 Tee 类的一个实例对象,然后我们把整个实例赋给 $tee 标量。现在,无论什么时候我们向 $tee 进行写入操作,我们都同时向两个位置进行写操作。 *更多文件操作。。。* *从一个文件的完全路径中找出它的名字*
复制内容到剪贴板
代码:
use File::Basename;
$path = "/docs/sitecircus.com/html/tricks/trick.of.the.week.html";
$basename = basename($path, ".html");
print $basename;
运行结果:trick.of.the.week 代码讨论:好了,成功了。问题是要找出文件的名字,要不带任何路径前缀,不带任何扩展名。File::Basename 模块可以使这很容易实现,我们只需要把文件的完全路径还有要剔除的扩展名传给它。上面的 path 变量是文件的完全路径,注意文件分隔符是 /,这个字符很特殊,因为它是 操作系统 的保留字符。这里你不能在文件名里使用系统的分隔符。你应该知道当今流行的操作系统都使用自己独特的文件分隔符: Unix使用 /,Windows 使用 /,Macintosh 使用 :(顺便说一下,在 Windows 上的 Perl 脚本中,你既可以使用 /也可以使用 /作为文件分隔符,Perl 的解释器能理解你的意思)。File::Basename,当然,能正确在完全路径中找到文件名,不论时在什么系统下。 *改变文件的所有者*
复制内容到剪贴板
代码:
($uid, $gid) = (getpwnam($username))[2,3]
    or die "$user not in passwd file";
chown ($uid, $gid, $file)
    or warn "couldn't chown $file.";
运行结果:无输出代码讨论:有的时候,你可能知道一个用户名,而你想用这个用户名做些事,比如改变一个文件的所有者。但是不幸的是,Perl 的 chown 命令不能接受用户名作为参数,但是可以接受一对数字:userid 和 groupid。虽然有这些不便之处,Perl 并没有让我们陷入困境,我们可以把用户名作为 getpwnam 函数的参数,获得一个数组,里面包含了用户名对应的 userid 和 groupid,分别对应着数组里的第二和第三个元素。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值