所以你想替换扩展名——来改变一个文件名。一旦您在 Perl 脚本中,就没有理由为此使用 shell。
更改扩展很容易“手动”完成(参见下面的库)。使用正则表达式
my $new_filename = $filename =~ s/.*\.\K.*/$new_extension/r;
.*
贪婪地匹配到最后一个(模式中的后面.
),\K
然后丢弃所有匹配项,以便我们只替换它后面的内容。或者,使用字符串尾锚$
my $new_filename = $filename =~ s/\.\K[^.]+$/$new_extension/r;
匹配并替换.
字符串末尾的所有非字符.
。在这两种情况下,修饰符/r
都使它返回新字符串并保持原始字符串不变;没有它,字符串 ( $filename
) 将就地更改。
现在更改磁盘上文件的名称。标准工具是File::Copy
use File::Copy qw(move);
move $filename, $new_filename or die "Can't move: $!";
(如果您注意到内置的重命名,请保持冷静并走过它。请参阅其链接页面了解原因。)
一般来说,最可靠的方法当然是使用合适的库,并且有一些好的库可以用于此目的。这是有用的Path::Tiny(您需要安装)
use Path::Tiny;
my $path = path($filename);
my $new_fqn = $path->parent->child( $path->basename(qr/[^.]+/) . $new_ext );
请参阅此模块的链接文档,但这里是对上述内容的简要说明。
该方法以对象parent
的形式返回到最后一个组件(文件/目录)的路径Path::Tiny
。然后child
调用它的方法向它添加另一个组件。
为此,我们得到basename
(最后一个组件,在此使用中去掉了扩展名),然后将新的扩展名附加到它上面。瞧,我们得到了替换扩展名的整个路径。这确实会解析路径两次,一次 forparent
和一次 for basename
。
这样做的另一个好处是该模块也有一个move
方法,所以
$path->move($new_fqn);
完成工作。
模块检查错误,或者抛出它自己的类croaks
的异常。
旧的和尝试过的 UNIX 方法是使用核心File::Basename
use File::Basename;
my ($name, $path, $ext) = fileparse($filename, qr/\.[^.]*/);
my $new_fqn = "$path/$name.$new_ext";
然后使用File::Copy::move
重命名文件。