我需要一些文件操作方面的帮助,需要一些专家建议。
看起来我在某处犯了一个愚蠢的错误,但我无法抓住它。
我的目录中包含.txt
后缀的文件,例如file1.txt
,file2.txt
,file3.txt
。
我想为每个文件添加一个修订字符串,比如rev0
,然后打开修改后的文件。例如rev0_file1.txt
,rev0_file2.txt
,rev0_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;
}
答案 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
}