如何使用Bash脚本将所有下划线字符替换为多个文件名中的空白字符?使用这段代码,我们可以用短划线代替下划线。但它如何与空白一起工作?使用bash脚本将下划线替换为空格
for i in *.mp3;
do x=$(echo $i | grep '_' | sed 's/_/\-/g');
if [ -n "$x" ];
then mv $i $x;
fi;
done;
谢谢!
如何使用Bash脚本将所有下划线字符替换为多个文件名中的空白字符?使用这段代码,我们可以用短划线代替下划线。但它如何与空白一起工作?使用bash脚本将下划线替换为空格
for i in *.mp3;
do x=$(echo $i | grep '_' | sed 's/_/\-/g');
if [ -n "$x" ];
then mv $i $x;
fi;
done;
谢谢!
这应该这样做:
for i in *.mp3; do
[[ "$i" = *_* ]] && mv -nv -- "$i" "${i//_/ }"
done
[[ "$i" = *_* ]]
测试文件名中包含任何下划线的测试,如果是的话,将mv
文件,其中"${i//_/ }"
扩展到i
,所有的底线已被替换一个空间(见shell parameter expansions)。-n
至mv
表示no clobber
:不会覆盖任何存在的文件(非常安全)。 可选。-v
到mv
针对的是verbose
:会说出它在做什么(如果你想看看发生了什么)。 非常可选。--
在这里告诉mv
参数将从这里开始。这总是一个很好的做法,就好像文件名以-
开头,mv
将尝试将其解释为选项,并且脚本将失败。 非常好的练习。另一评论:当使用水珠(即for i in *.mp3
),它总是很好要么设置shopt -s nullglob
或shopt -s failglob
。如果没有文件匹配模式,前者将使*.mp3
扩展为空(因此循环将不会执行),后者将明确地引发错误。如果没有这些选项,如果没有匹配*.mp3
的文件,则循环中的代码将使用i
执行,其逐字值为*.mp3
,这可能会导致问题。 (好吧,因为后卫[[ "$i" = *_* ]]
,这里不会有任何问题,但始终使用这两种选项是个好习惯)。
希望这会有所帮助!
你的脚本使用空格失败的原因是当传递给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
使用tr
tr '_' ' ' <file1 >file2
为什么管道('|')?这甚至工作吗?'tr'_'''
是的,好点。 – cmh
这很好,干净。 +1 –
你太棒了!非常感谢你们! – stardust
...可以更好地写成'[[“$ i”==“* _ *”]]',因为这样可以减少混淆,而'=='用于测试,'='用于赋值(根本不需要在手册页中没有找到语法'[[LHS = RHS]]')。 –