文件命名中加空格是很正常的事情,但这种命名方式给Linux命令行工具和Shell带来了困扰,因为大多数命令中,都是默认以空格做为值与值之间的分隔符,而不是做为文件名的一部分。

我在最近迁移博客的过程中就踩到这个坑,先看脚本:

for i in $(ls *.md)
do
line=$(egrep -n "^---" "${i}" | tail -n 1 | awk -F: '{print $1-1}')
sed -i "${line}d" ${i}
done

我希望把当前目录下所有md文档的最后一个以---开头的前一行删掉(这一行是空行)

然而执行结果如下:

egrep: cluster自带wp管理密码.md: No such file or directory
sed: can't read cluster自带wp管理密码.md: No such file or directory
egrep: 用: No such file or directory
sed: can't read 用: No such file or directory
egrep: openpyxl: No such file or directory
sed: can't read openpyxl: No such file or directory
...

出问题的都是命名中带空格的文件

那怎么处理这些带空格的文件呢?一个终极的解决办法就是设置IFS(the Internal Field Separator),不要用空格做为IFS,选择其他的符号。先来看看man page:

IFS: The Internal Field Separator that is used for word splitting after expansion and to split lines into words with the read built-in command. The default value is “”.

所以只需要在批处理的脚本前加一行

IFS=$(echo -en "\n\b")

搞定~

参考:

  1. Work the shell - Dealing with Spaces in Filenames
  2. BASH SHELL:For Loop File Names With Spaces
  3. SHELL技巧:处理文件名中的那些空格