使用Perl One Liner重命名匹配文件时出错

时间:2019-07-04 17:40:43

标签: regex perl unix file-rename

我想重命名所有与模式匹配的文件。 这种衬板通常对我有用,但是我遇到了一些错误。

我拥有的文件名种类:PMSNpoda5718_1p2g_out_fst.txt SCSNpoda5718_1p2g_out_fst.txt

我想要的文件名:PM-SN_poda5718_1p2g_out_fst.txt SC-SN_poda5718_1p2g_out_fst.txt

我的第一次尝试是:

ls *fst.txt | perl -ne '/^([A-Z][A-Z])([A-Z][A-Z])(poda.*?$)/; system("mv $_ $1-$2_$3")'

但这没用。

最后,我想出了一行可以准确打印出我想要的东西

ls *fst.txt | perl -lne '/([a-zA-Z]{2})([a-zA-Z]{2})(poda.*?$)/; print "mv $_ $1-$2_$3"'

打印:

mv PMSNpoda5718_1p2g_out_fst.txt PM-SN_poda5718_1p2g_out_fst.txt
mv SCSNpoda5718_1p2g_out_fst.txt SC-SN_poda5718_1p2g_out_fst.txt

但是当我使用它来重命名文件时:

ls *fst.txt | perl -lne '/([a-zA-Z]{2})([a-zA-Z]{2})(poda.*?$)/; system("mv $_ $1-$2_$3")'

我明白了

sh: $'32mPMSNpoda5718_1p2g_out_fst.txt\E[0m': command not found
mv: missing destination file operand after ''$'\033''[01'
Try 'mv --help' for more information.
sh: $'32mSCSNpoda5718_1p2g_out_fst.txt\E[0m': command not found
mv: missing destination file operand after ''$'\033''[01'
Try 'mv --help' for more information.

再次添加回声

ls *fst.txt | perl -lne '/([a-zA-Z]{2})([a-zA-Z]{2})(poda.*?$)/; system("echo mv $_ $1-$2_$3")'

我明白了

mv
h: $'32mPMSNpoda5718_1p2g_out_fst.txt\E[0m': command not found
mv
h: $'32mSCSNpoda5718_1p2g_out_fst.txt\E[0m': command not found

有人可以指出这是什么错误,以便我了解我在做什么错吗?

谢谢!

1 个答案:

答案 0 :(得分:4)

没有理由通过外壳程序运行重命名。

ls -1 *fst.txt | perl -MFile::Copy=move -wlnE'
    $new = s/([a-zA-Z]{2})([a-zA-Z]{2})/$1-$2_/r; move $_, $new'

请注意-1上的ls选项,以便每行确实获得一个文件名。

32m[0m是ANSI转义符,可以为终端设置颜色(和其他属性),通常用于外壳配置(例如提示)。也许您的ls正在将它们推出,而mv正在将它们与之混淆?另一个例子说明为什么最好避免通过外壳,除非有必要。

在某些Shell中,现有的别名实际上是通过各种选项运行命令(这就是ls输出被这些代码“修饰”的原因),可以通过在命令前加上反斜杠来消除该别名, \ls

另一种选择是尽可能减少对系统的依赖,并在程序中建立文件列表。

perl -MFile::Copy=move -wE'
    for (glob "*fst.txt") { 
        $new = s/([a-zA-Z]{2})([a-zA-Z]{2})/$1-$2_/r;
        move $_, $new or warn "Cant rename $_ to $new: $!" }'

glob上现在负责建立正确的文件列表。