Perl5中19个最重要的文件系统工具

在写脚本处理文件系统时,经常需要加载很多模块。其中好多有用函数分散在各种不同的模块中。它们有些是Perl的内置函数,有些是在同Perl一起发行的标准模块中,另外一些是通过CPAN安装的。

下面来看15个最常用的工具。

 

 

 

当前路径

我经常需要知道当前所在的文件夹是什么。Cwd 模块有一个同名但是小写的函数 cwd,它会返回当前工作目录。

 

  1. use strict;
  2. use warnings;
  3.  
  4. use Cwd qw(cwd);
  5.  
  6. print cwd, "\n";

 

 

临时文件夹

我经常需要创建一批临时文件,并且确保它们在脚本结束的时候会被自动删除。要满足这个需求,最简单的方法是以 CLEANUP 选项使用 File::Temp 模块的 tempdir 函数来创建一个临时文件夹。

 

 

  1. use strict;
  2. use warnings;
  3. use autodie;
  4.  
  5. use File::Temp qw(tempdir);
  6.  
  7. my $dir = tempdir( CLEANUP => 1 );
  8.  
  9. print "$dir\n";
  10.  
  11. open my $fh, '>', "$dir/some_file.txt";
  12. print $fh "text";
  13. close $fh;

 

 

与操作系统无关的路径

如果上面的代码要在 Linux 和 Windows 上都要运行,人们会习惯在 Windows 平台上用反斜线分割路径。否则,在VMS上不能执行。而这就是 File::Spec::Functions模块中catfile函数的用武之地。

 

  1. use strict;
  2. use warnings;
  3.  
  4. use File::Spec::Functions qw(catfile);
  5.  
  6. use File::Temp qw(tempdir);
  7.  
  8. my $dir = tempdir( CLEANUP => 1 );
  9.  
  10. print "$dir\n";
  11. print catfile($dir, 'some_file.txt'), "\n";

执行这个代码后,能看到临时文件夹被打印出来,紧跟其后的是文件名字。

 

切换目录

通常情况下,先切换工作目录到临时文件夹再进行操作会更简单。但是也存在其他情况的写测试。此时我们可以使用内置函数chdir。

 

 

  1. use strict;
  2. use warnings;
  3. use autodie;
  4.  
  5. use File::Temp qw(tempdir);
  6. use Cwd;
  7.  
  8. my $dir = tempdir( CLEANUP => 1 );
  9. print cwd, "\n";
  10. chdir $dir;
  11. print cwd, "\n";
  12.  
  13. open my $fh, '>', 'temp.txt';
  14. print $fh, 'text';
  15. close $fh;

以上看起来可以正常工作,但是当File::Temp尝试删除文件夹,而我们仍然“在里面”(之前切换工作目录到它)时就会有问题。

例如,我会得到下面的错误信息:

 

cannot remove path when cwd is /tmp/P3DZP_rmqg for /tmp/P3DZP_rmqg:

为了避免这种情况,我通常会在切换目录之前保存cwd的返回值,并且在最后再次调用chdir。

 

  1. my $original = cwd;
  2.  
  3. ...
  4.  
  5. chdir $original;

这样仍然会有个小问题。如果我在脚本中间调用exit(),或者在执行到chdir $original之前抛出异常而终止脚本,会发生什么?

Perl提供了一个解决方案:把最后一个chdir包裹在END块中。如此,就会确保无论何时、以何种方式退出脚本,这些代码都会执行到。

 

  1. my $original = cwd;
  2.  
  3. ...
  4.  
  5. END {
  6. chdir $original;
  7. }

 

 

相对路径

当写一个多文件构成的项目(例如一个或多个脚本,多个模块,也可能是多个模板),并且我不想“安装”它们时,最好的目录组织方式是:确保每个文件都在一个固定的相对位置。

所以,我的项目目录通常会包含一个脚本子文件夹,一个模块文件夹(lib), 一个模板文件夹, 等等:

 

project/
     scripts/
     lib/
     templates/

那么,如何才能确保脚本能够找到模板? 我有好几个处理办法:

 

 

  1. use strict;
  2. use warnings;
  3. use autodie;
  4.  
  5. use FindBin qw($Bin);
  6. use File::Basename qw(dirname);
  7. use File::Spec::Functions qw(catdir);
  8.  
  9. print $Bin, "\n"; # /home/foobar/Rocket-Launcher/scripts
  10. print dirname($Bin), "\n"; # /home/foobar/Rocket-Launcher
  11. print catdir(dirname($Bin), 'templates'), "\n"; # /home/foobar/Rocket-Launcher/templates

FindBin模块导出的参量$bin存放着当前脚本的目录路径。 在我们的例子中就是指向project/scripts/文件夹的路径。

File::Basename中的dirname函数会传入一个路径,并返回除最后一部分之外的路径。

最后一行File::Spec::Functions模块的catdir函数基本上和我们之前看到的catfile一样。

除了打印到屏幕上,当然也可以使用catdir的返回值来表示templates路径。

 

从相对路径中加载模块

大部分情况下,要查找和加载的模块都会在项目的lib/文件夹中。为此,我们会把之前的代码和lib指令连用。这样会改变@INC变量的值,把相对路径添加在数组开头。

 

  1. use strict;
  2. use warnings;
  3. use autodie;
  4.  
  5. use FindBin qw($Bin);
  6. use File::Basename qw(dirname);
  7. use File::Spec::Functions qw(catdir);
  8.  
  9. use lib catdir(dirname($Bin), 'lib');
  10.  
  11. use Rocket::Launcher;

假定存在lib/Rocket/Launcher.pm文件。

posted @ 2016-11-03 16:29  nkwy2012  阅读(646)  评论(0编辑  收藏  举报