2012-12-19 77 views
0

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

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

谢谢!

回答

9

这应该这样做:

for i in *.mp3; do 
    [[ "$i" = *_* ]] && mv -nv -- "$i" "${i//_/ }" 
done 
  • 如果[[ "$i" = *_* ]]测试文件名中包含任何下划线的测试,如果是的话,将mv文件,其中"${i//_/ }"扩展到i,所有的底线已被替换一个空间(见shell parameter expansions)。
  • 选项-nmv表示no clobber:不会覆盖任何存在的文件(非常安全)。 可选
  • 选项-vmv针对的是verbose:会说出它在做什么(如果你想看看发生了什么)。 非常可选
  • --在这里告诉mv参数将从这里开始。这总是一个很好的做法,就好像文件名以-开头,mv将尝试将其解释为选项,并且脚本将失败。 非常好的练习

另一评论:当使用水珠(即for i in *.mp3),它总是很好要么设置shopt -s nullglobshopt -s failglob。如果没有文件匹配模式,前者将使*.mp3扩展为空(因此循环将不会执行),后者将明确地引发错误。如果没有这些选项,如果没有匹配*.mp3的文件,则循环中的代码将使用i执行,其逐字值为*.mp3,这可能会导致问题。 (好吧,因为后卫[[ "$i" = *_* ]],这里不会有任何问题,但始终使用这两种选项是个好习惯)。

希望这会有所帮助!

+0

这很好,干净。 +1 –

+0

你太棒了!非常感谢你们! – stardust

+0

...可以更好地写成'[[“$ i”==“* _ *”]]',因为这样可以减少混淆,而'=='用于测试,'='用于赋值(根本不需要在手册页中没有找到语法'[[LHS = RHS]]')。 –

2

你的脚本使用空格失败的原因是当传递给mv时,文件名被视为多个参数。您需要引用文件名,以便每个文件名都被视为一个简单的名称。更新相关线路与你的脚本:

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

顺便说一句,如果你已经安装了perl version of the rename command,你跳过脚本,并使用达到同样的事情:

rename 's/_/ /' *.mp3 

或者,如果你有more classic rename command

rename "_" " " *.mp3 
1

使用tr

tr '_' ' ' <file1 >file2 
+0

为什么管道('|')?这甚至工作吗?'tr'_''' file2'应该够了,重定向输入输出 – KurzedMetal

+0

是的,好点。 – cmh