重命名目录中的所有.txt文件,然后在perl中打开该文件

时间:2014-05-05 18:13:43

标签: perl

我需要一些文件操作方面的帮助,需要一些专家建议。

看起来我在某处犯了一个愚蠢的错误,但我无法抓住它。

我的目录中包含.txt后缀的文件,例如file1.txtfile2.txtfile3.txt

我想为每个文件添加一个修订字符串,比如rev0,然后打开修改后的文件。例如rev0_file1.txtrev0_file2.txtrev0_file3.txt

我可以附加rev0,但我的程序无法打开文件。

以下是我的代码的相关部分

my $dir   = "path to my directory";
my @::tmp = ();

opendir(my $DIR, "$dir") or die "Can't open directory, $!";
@::list = readdir($DIR);
@::list2 = sort grep(/^.*\.txt$/, @::list);
foreach (@::list2) {
  my $new_file = "$::REV0" . "_" . "$_";
  print "new file is $new_file\n";
  push(@::tmp, "$new_file\n");
}
closedir($DIR);

foreach my $cur_file (<@::tmp>) {
  $cur_file = $_;
  print "Current file name is $cur_file\n"; # This debug print shows nothing
  open($fh, '<', "$cur_file") or die "Can't open the file\n"; # Fails to open file;
}

4 个答案:

答案 0 :(得分:2)

你的问题在这里:

foreach my $cur_file(<@::tmp>) {
    $cur_file = $_;

您正在使用循环变量$cur_file,但是使用$_覆盖它,在此循环中根本不使用它。要解决此问题,只需删除第二行。

答案 1 :(得分:1)

您最大的问题是您在循环中使用$cur_file作为文件名,但随后$_重新分配$_即使$::REV0没有值在那时候。此外,正如鲍罗丁指出的那样,move从未定义过。

您可以使用File::Copy中的File::Find命令移动文件,您可以使用use strict; use warnings; use feature qw(say); use autodie; use File::Copy; # Provides the move command use File::Find; # Gives you a way to find the files you want use constant { DIRECTORY => '/path/to/directory', PREFIX => 'rev0_', }; my @files_to_rename; find ( sub { next unless /\.txt$/; # Only interested in ".txt" files push @files_to_rename, $File::Find::name; }, DIRECTORY ); for my $file ( @files_to_rename ) { my $new_name = PREFIX . $file; move $file, $new_name; $file = $new_name; # Updates @files_to_rename with new name open my $file_fh, "<", $new_name; # Open the file here? ... close $file_fh; } for my $file ( @files_to_rename ) { open my $file_fh, "<", $new_name; # Or, open the file here? ... close $file_fh; } 查找要移动的文件:

$file = $new_name

了解如何使用Perl模块使您的任务更轻松? Perl附带了数百个预先安装的软件包来处理zip文件,tarball,时间,电子邮件等。您可以在Perldoc页面找到一个列表(确保选择您正在使用的Perl版本) !)。

@files_to_rename实际上正在$::数组内更改文件名的值。这是一个小小的Perl技巧。这样,即使通过重命名,您的数组也会引用该文件。

您有两种选择可以打开文件进行阅读:您可以先重命名所有文件,然后再次循环打开每个文件,也可以在重命名后打开它们。我两个地方都闪闪发光。

根本不使用use strict;。这是非常糟糕的形式,因为它会覆盖use strict - 即如果您正在使用my开头。除非必须,否则标准不是使用包变量(又名全局变量)。相反,您应该使用由my定义的词法范围变量(又名局部变量)。

close变量的一个优点是,我真的不需要{{1}}命令,因为变量在循环的每次迭代时都超出范围,并且一旦循环就完全消失完成了。当包含文件句柄的变量超出范围时,文件句柄将自动关闭。

答案 2 :(得分:0)

您尝试存储的内容是@::tmp中文件的更新名称。该文件尚未重命名,因此代码die d并不奇怪,因为它无法找到重命名的文件。

由于它只是重命名,请考虑以下代码:

use strict;
use warnings;
use File::Copy 'move';

for my $file ( glob( "file*.txt" ) ) {

    move( $file, "rev0_$file" )
      or die "Unable to rename '$file': $!";
}

从命令行/终端,考虑rename实用程序(如果可用):

$ rename file rev0_file file*.txt

答案 3 :(得分:0)

始终在每个脚本的顶部加入use strict;use warnings。只要您进行文件或目录处理,就use autodie;

您没有理由为::添加变量前缀,因此请简化以下代码:

use strict;
use warnings;
use autodie;

use File::Copy;

my $dir = "path to my directory";

chdir($dir); # Make easier by removing the need to prefix path information

foreach my $file (glob('*.txt')) {
    my $newfile = 'rev0_'.$file;
    copy($file, $newfile) or die "Can't copy $file -> $newfile: $!";

    open my $fh, '<', $newfile;
    # File processing
}