我想将专用文件移动到其当前文件夹的子文件夹中。这项工作(带有一个专用文件):
qx/mv -v 'the name of the file' TRANS/; # TRANS is the subfolder at the same level as 'my file'
但是以下操作无效:
while (defined($_ = <PODCASTS>)) {
if (/ \d{1}\.mp3$/) {
print $_;
qx/mv -f -v "$_" TRANS/;
die; # for testing on first occurrence
};
}
给出哪个(Ariane ...Tadjikistan 1.mp3
是文件的实际名称):
mv: rename Ariane Zevaco autour des Musiciens populaires au Tadjikistan 1.mp3
to TRANS/Ariane Zevaco autour des Musiciens populaires au Tadjikistan 1.mp3: No such file or directory
我使用了许多无用的报价变体(给出各种错误注释)。
答案 0 :(得分:4)
直接的问题是您没有从文件句柄中读取的行中删除该尾随换行符。
也就是说,不要依赖shell解析,而要使用安全的方式将未经修改的参数传递给调用的程序:
system(qw(mv -f -v --), $_, 'TRANS/');
注意::您要将整行传递给命令,该命令将包括行尾。您应该先chomp
行。
引用perlfunc:
system LIST
...如果LIST中有多个参数, 或者,如果LIST是具有多个值的数组,则启动 列表的第一个元素带有参数给出的程序 由列表的其余部分给出。
用C语言来讲,程序的main()
函数将用argc == 4
调用,而argv[2]
将从您的Perl脚本中接收$_
的内容。
替代解决方案
对于这个简单的问题,您实际上不需要外壳。您可以简单地使用Perl rename()
function
奖金代码,我建议重写您的代码,使其更加符合Perl习惯:
use strict;
use warnings;
use POSIX qw(:sys_wait_h);
while (<PODCASTS>) {
if (/ \d\.mp3$/) {
chomp;
print "$_\n";
system(qw(mv -f -v --), $_, 'TRANS/');
die "Can't execute \"mv\": $!\n"
if $? < 0;
die '"mv" killed by signal ' . WTERMSIG($?) . "\n"
if WIFSIGNALED($?);
die '"mv" exited with error ' . WEXITSTATUS($?) . "\n"
if WEXITSTATUS($?);
}
}
奖金代码2 :如何用内置的Perl函数替换system('mv', ...)
:
my $target = "TRANS/$_";
# Emulate the "mv -f" option
unlink($target) || $!{ENOENT}
or die "unlink: $!\n";
# same as "mv"
rename($_, $target)
or die "rename: $!\n";