如何使用Perl的qx mv文件到目录?

时间:2019-02-09 15:36:42

标签: perl

我想将专用文件移动到其当前文件夹的子文件夹中。这项工作(带有一个专用文件):

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

我使用了许多无用的报价变体(给出各种错误注释)。

1 个答案:

答案 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";