Perl:重命名对$ value filename不起作用

时间:2015-12-09 06:50:09

标签: perl

我想用不同调用的同一文件的副本填充文件夹。我使用Windows filelist.txt创建了cmd以获取文件名,然后使用以下代码:

use strict;    # safety net
use warnings;  # safety net
use File::NCopy qw(copy);

open FILE, 'C:\blabla\filelist.txt';
my @filelist = <FILE>;
my $filelistnumber = @filelist + 1;
my $file = 0;
## my $filename = 'null.txt';
my $filename = $filelist[$file];


while( $file < $filelistnumber ){

    copy('base.smp','temp.smp');
    rename 'temp.smp', $filename;

    $file = $file + 1;

};

如果我尝试将其重命名为'test.smp'或其他什么,它就可以了。如果我尝试上面的代码,我会得到这个:

Use of uninitialized value $filename in print at blablabla/bla/bla.pl line 25, <FILE> line 90.

我做错了什么?我觉得有一些小错误,可能是语法错误,一直在躲避我。

2 个答案:

答案 0 :(得分:3)

首先,这里有一些改进的代码:

use strict;
use warnings;
use File::Copy;

while (<>) {
    chomp;
    copy('base.smp', $_) or die $!;
}

您将其保存为script.pl并按如下方式调用它:

$ perl script.pl C:\blabla\filelist.txt

这段代码在哪些方面有所改进?

  • 它使用核心模块File::Copy而不是已弃用的File::NCopy
  • 它使用null filehandle或“菱形运算符”(<>)隐式迭代作为命令行参数给出的文件,这样简单而优雅。
  • copy()由于某种原因失败的情况下处理错误。
  • 它不使用while循环或C风格的for循环来迭代数组,这些数组都容易出现一个错误而忘记重新分配正如你所发现的那样,迭代器。
  • 它不使用open()的旧2参数语法。 (嗯,不明确,但这超出了这个答案的范围。)
  

我做错了什么?我觉得有一些小错误,一个   可能是语法错误,这一直在躲避我。

语法错误会导致出现错误消息,指出存在语法错误。但既然你问你做错了什么,那就让我们来看看吧:

use File::NCopy qw(copy);

此模块最后一次更新于2007年,并标记为已弃用。不要使用它。

open FILE, 'C:\blabla\filelist.txt';

您应该使用open的三参数形式,使用词法文件句柄,并始终检查系统调用的返回值。

my @filelist = <FILE>;

您很少需要将整个文件粘贴到内存中。在这种情况下,你没有。

my $filelistnumber = @filelist + 1;

这条线没有任何内在错误,但是当你考虑以后如何使用它时。请记住,数组是0索引的,因此您只需设置一个超出范围的数组索引。但我们会在一秒钟之内完成。

my $filename = $filelist[$file];

您通常希望在循环中执行此分配,以免在递增计数器后忘记更新它(这正是此处发生的事情)。

while( $file < $filelistnumber ){

这是在Perl中迭代数组的奇怪方法。您可以使用典型的C-style for loop,但最常用的是使用foreach-style loop

for my $element (@array) {
    ...
}

列表的每个元素都本地化为循环,您不必担心计数器,条件或数组边界。

copy('base.smp','temp.smp');

同样,请务必检查系统调用的返回值。

rename 'temp.smp', $filename;

无需copy rename。您可以第一次复制到最终目标文件名。但是如果 要重命名,请始终检查系统调用的返回值。

};

块不需要像simple statements这样的分号终止。

答案 1 :(得分:0)

您应该避免使用裸字文件句柄。打开时,您应该使用类似的文件引用打开,并确保在失败时捕获它:

open(my $fh, '<', 'C:\blabla\filelist.txt') or die "Cannot open filelist.txt: $!";

$ fh变量将包含您的文件引用。

对于您的问题,看起来您的filelist.txt必须为空。尝试使用Data :: Dumper打印出@filelist以确定它的内容。

use Data::Dumper;

编辑:

看起来您还希望将$ filename变量设置为列表中的每个迭代的下一个变量,因此将$filename = $filelist[$file];放在循环的开头。

你的问题可能是你循环太远了?尝试删除+ 1

中的my $filelistnumber = @filelist + 1;