我有一些 .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-rename
或prename
。 prename
通常是较旧的有缺陷的版本。