使用 perl one liner 重命名匹配文件时出错

Error renaming matching files with perl one liner

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

我的文件名种类: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 $_ -_")'

但是没有用。

最后我想到了一行打印出我想要的内容

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

打印:

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 $_ -_")'

我明白了

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

再次添加 echo

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

我明白了

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

谁能指出我哪里出错了,这样我就能明白我做错了什么?

谢谢!

没有理由 运行 通过 shell 重命名。

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

请注意 ls 上的 -1 选项,这样您就可以每行获得一个文件名。

32m[0m 是 ANSI 转义符,可以为终端设置颜色(和其他属性),通常用于 shell 配置(例如提示)。或许您的 ls 发布了这些内容,而 mv 对它们感到非常困惑?另一个例子说明为什么最好避免通过 shell,当然除非必要。

在某些 shell 中存在别名,因此命令实际上 运行 具有各种选项(这就是 ls 输出使用这些代码得到 "dressed" 的原因), 可以通过在命令前加上反斜杠 \ls 来抑制。

另一个选择是尽量减少对系统的依赖,在程序中也建立文件列表

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

构建正确文件列表的责任现在在 glob