从终端批量重命名文件

从终端批量重命名文件

我有一些 .mp3 文件,它们的扩展名中带有 $ 符号,我想删除它们,它们被命名为:

1.mp3$$
2.mp3$$
etc.

他们必须是

1.mp3
etc.

我试过

for f in *; do a="(echo $f | sed s/mp3$$/mp3/)"; mv "$f" "$a"; done

但这给出了错误消息

mv: rename 1.mp3$$ to (echo 1.mp3$$ | sed s/mp3582/mp3/): No such file or directory

对于每个文件。

然后阅读完答案后问题,我试过了

for i in *mp3$$; do mv "$i" "mp3"; done

但这不仅不起作用,还导致除一个文件外的所有文件都被删除,只剩下一个名为“mp3”的文件。它还给出了错误消息

mv: rename *mp3582 to mp3: No such file or directory

幸运的是我仍然有原始文件并且仍然想重命名它们,但是如何通过命令行将“mp3$$”更改为“mp3”?

另外,为什么上面的第二条命令会导致除一个文件之外的所有文件被删除?

为什么错误消息包含序列“3582”,而该序列不在任何文件名中?

PS 我也已经尝试过在命令中使用 \$ 而不是 $ 来转义 $ 字符,但这也不起作用。

答案1

$$扩展为所有 POSIX 兼容 shell 中 shell 的进程 ID。

更改*.mp3$$文件*.mp3可以这样完成:

for i in *.mp3\$\$; do mv -i "$i" "${i%%\$\$}"; done 

您的第二个命令行显然是由 PID 为 582 的 shell 执行的,因此它被扩展为:

for i in *mp3582; do mv "$i" "mp3"; done

然后,由于没有任何内容可能与通配符表达式匹配,因此循环将仅执行一次,并将通配符表达式按原样放置在变量中$i

mv "*mp3582" "mp3" 
mv: rename *mp3582 to mp3: No such file or directory

您的第二次尝试还会将每个文件依次重命名为固定文件名“mp3”,如果“mp3”不是已存在的目录,则用该名称覆盖任何先前的文件。如果您也尝试以转义形式进行操作,这可能可以解释为什么除一个文件外的所有文件都被删除:

for i in *mp3\$\$; do mv "$i" "mp3"; done

这会做:

mv <filename1>.mp3$$ mp3
mv <filename2>.mp3$$ mp3   # overwrites the previous "mp3"
mv <filename3>.mp3$$ mp3   # overwrites the previous "mp3" again
...

您最初的尝试实际上是可以修复的:

for f in *; do a="(echo $f | sed s/mp3$$/mp3/)"; mv "$f" "$a"; done   # your version
for f in *; do a="$(echo \"$f\" | sed s/mp3\\$\\$/mp3/)"; mv "$f" "$a"; done    # fixed version

仅括号内的命令或管道将不会被执行:您需要$( ... )为此构造。在其周围添加双引号以处理可能包含空格、分号或其他棘手字符的输出。

然后,get中的$字符$( ... )通过解释器传递两次:一次是在解析整个命令行时,另一次是在$( ... )解析构造以供执行时。在每次传递中,反斜杠转义字符都会被删除。因此,您需要双反斜杠来为 sed 保留“mp3$$”。

另外, $f 需要用双引号引起来,以防文件名包含空格或其他棘手的字符...并且双引号需要转义,因为它们位于另一组双引号内,我们希望保留它们以供传递$( ... )

答案2

你可以试试这个

for file in *.mp3\$\$; do mv -v "$file" "${file/.mp3\$\$/.mp3}"; done

答案3

使用该perl rename实用程序(不是rename来自 的命令util-linux,它具有完全不同且不兼容的命令行选项):

rename -n -v 's/\$+//g' *.mp3*

这将删除全部 $字符来自任何地方在文件名中。

如果您希望它仅删除$文件名末尾的字符:

rename -n -v 's/\$+$//' *.mp3*

顺便说一句,上面的命令使用rename's-n选项作为试运行,向您展示rename在不实际重命名任何内容的情况下会做什么。当您确定它完全按照您的要求执行并且不会产生任何意外后果时,请-n从命令行中删除 。也可以选择删除-v(详细)选项。


perl重命名实用程序位于Debianrename及其派生发行版的软件包中。该软件包包含文件::重命名CPAN 模块和rename实用程序。

Debian 上该软件包的早期版本perl曾经包含旧版本的rename,但存在一些值得注意的错误。如果您安装了该版本,则应rename尽快安装该软件包。

这个基于 perl 的rename有时也安装为file-renameprenameprename通常是较旧的有缺陷的版本。

相关内容