调试Perl one-liner以重命名文件

时间:2012-07-06 20:49:06

标签: perl

我正在测试/尝试this Perl one-liner,我正在试图弄清楚文件发生了什么。我再也看不到这些文件了。 我删除了它们或出了什么问题吗?

列出的文件名示例(原始):

IMG_0178.JPG
IMG_0182.JPG
IMG_0183.JPG
IMG_0184.JPG
IMG_0186.JPG

我想将文件扩展名更改为小写(.jpg):

perl -e'while(<*.JPG>) { s/JPG$/jpg/; rename <*.jpg>, $_ }'

2 个答案:

答案 0 :(得分:9)

不要将rename与glob一起使用。使用标量。尝试在替换之前将文件名分配给新变量,并将旧名称重命名为修改后的名称,如下所示:

perl -e'while(<*.JPG>) { ($new = $_) =~ s/JPG$/jpg/; rename $_, $new }'

使用ls -1检查输出:

IMG_0178.jpg                                                                                                     
IMG_0182.jpg                                                                                                
IMG_0183.jpg                                                                                              
IMG_0184.jpg                                                                                               
IMG_0186.jpg

答案 1 :(得分:4)

你的代码应该做你想做的事。

标量上下文中的<*.JPG>之类的文件全局将返回与模式匹配的下一个文件,并且由于whilerename都应用了标量上下文,因此两个globs返回相同的值在每次迭代中。

while (<*.JPG>) {
    s/JPG$/jpg/;
    rename <*.jpg>, $_;
}

在循环的第一次迭代中,$_IMG_0178.JPG设置为while,替换将文件类型设置为小写。

然后在重命名<*.jpg>中在标量上下文中执行并再次返回IMG_0178.JPG - 同一列表中的第一个文件,因为Windows文件名不区分大小写。

所以最后重命名会根据需要执行rename 'IMG_0178.JPG', 'IMG_0178.jpg'

像这样重写rename清楚地表明了这一点

sub ren($$) {
  print "$_[0] -> $_[1]\n";
}

while (my $file = <*.JPG>) {
  $file =~ s/JPG$/jpg/;
  ren <*.JPG>, $file;
}

<强>输出

IMG_0178.JPG -> IMG_0178.jpg
IMG_0182.JPG -> IMG_0182.jpg
IMG_0183.JPG -> IMG_0183.jpg
IMG_0184.JPG -> IMG_0184.jpg
IMG_0186.JPG -> IMG_0186.jpg

所以你很幸运,你的文件应该已经根据需要重命名了。

这样做。特别是你应该使用print语句来代替任何关键操作运行程序,以便你可以看到将要发生的事情。

这会更好,因为id更清楚地表达了什么

perl -e '($f = $_) =~ s/JPG$/jpg/i and rename $_, $f while <*.JPG>'