1

如何使用 Bash 脚本将多个文件名中的所有下划线字符替换为空格?使用此代码,我们可以用破折号替换下划线。但它如何与空白一起使用?

for i in *.mp3;
do x=$(echo $i | grep '_' | sed 's/_/\-/g');
if [ -n "$x" ];
then mv $i $x;
fi;
done;

谢谢!

4

3 回答 3

9

这应该这样做:

for i in *.mp3; do
    [[ "$i" = *_* ]] && mv -nv -- "$i" "${i//_/ }"
done
  • 该测试[[ "$i" = *_* ]]测试文件名是否包含任何下划线,如果包含下划线,则会mv将文件"${i//_/ }"扩展为i所有下划线已被空格替换的位置(请参阅shell 参数扩展)。
  • 选项意味着:-n不会覆盖任何现有文件(非常安全)。可选mvno clobber
  • 选项-vmvfor verbose: 会说明它在做什么(如果你想看看发生了什么)。非常可选
  • 这里--是为了说明mv争论将从这里开始。这始终是一个好习惯,就像文件名以 开头一样-mv会尝试将其解释为一个选项,并且您的脚本将失败。很好的练习

另一条评论:当使用 glob(即for i in *.mp3)时,设置shopt -s nullglobshopt -s failglob. 如果没有文件与模式匹配,前者将*.mp3扩展为空(因此不会执行循环),后者将显式引发错误。如果没有这些选项,如果不*.mp3存在匹配的文件,则循环内的代码将使用可能导致问题i的逐字值执行。*.mp3(好吧,这里不会有任何问题,因为有 guard [[ "$i" = *_* ]],但是总是使用任何一个选项都是一个好习惯)。

希望这可以帮助!

于 2012-12-19T18:32:52.820 回答
2

您的脚本因空格而失败的原因是文件名在传递给mv. 您需要引用文件名,以便将每个文件名视为一个单独的参数。更新脚本中的相关行:

mv "$i" "$x"  
# where $i is your original filename, and $x is the new name

顺便说一句,如果您安装了perl 版本的 rename 命令,您可以跳过脚本并使用以下方法实现相同的目的:

rename 's/_/ /' *.mp3

或者,如果您有更经典的rename命令

rename "_" " " *.mp3
于 2012-12-19T18:25:19.600 回答
1

使用tr

tr '_' ' ' <file1 >file2
于 2012-12-19T18:26:36.647 回答