4

我正在测试/试用这个 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>, $_ }'
4

2 回答 2

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
于 2012-07-06T20:54:03.943 回答
4

奇怪的是你的代码应该做你想做的事。

标量上下文中的文件 glob<*.JPG>将返回与模式匹配的下一个文件,并且由于两者都while应用rename标量上下文,因此两个 glob 在每次迭代时返回相同的值。

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

在循环的第一次迭代中,由$_设置为,并且替换将文件类型设置为小写。IMG_0178.JPGwhile

然后在<*.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>'
于 2012-07-06T21:36:31.050 回答