shell 如何处理带有空格的文件名

疑难杂症  

场景

对目录下的所有文件进行打包并加密码 但是某些文件名中存在空格例如 “xxxx .psd”

报错提示

    zip warning: name not matched: ./风格搞0506.psd

zip error: Nothing to do! (try: zip -rP xxxx /data/cos/test/d1ee1633d80e92e0740b8201812fc331.zip . -i ./xxxx .psd)  
  • 从结果来看,由于文件名中空格的存在,一个文件名被分为了两个。所以,要想办法避免 shell 按空格分离字符串。

shell 中的 IFS

  • shell 中有一个叫做 Internal Field Seprator 的变量,简称 IFS,译为内置分隔符。终端下通过 set | grep IFS 可以看到该变量的默认值是空格,制表符和换行符。也就是说 shell 会默认以上述三种字符对字符串进行分隔。这样就不难理解上述脚本将一个文件名分为两个的原因了。

  • 所以,将 IFS 中的空格去掉,文件名就不会被分开了。

IFS=$'\t\n'  

解决后的脚本示例

#!/bin/bash


zipass="xxxxxxx"  
package_dir=/data/cos

# 备份默认的IFS
IFS_OLD=$IFS

# 通过对 IFS 重新赋值可以重新定义 shell 中对字符串的默认分隔符。
IFS=$'\t\n'

function package_file(){  
    filemd5=$2
    filename=$3
    project=$1
    cd /data/samba/$project

    if [ -f ${package_dir}/${project}/${filemd5}.zip ];then
       echo "$filename is not modify,so pass"
    else
       zip -rP $zipass ${package_dir}/${project}/${filemd5}.zip "${filename}"
    fi
}


function check_file_list(){  
    project=$1
    cd /data/samba/$project
    for i in $(find . -type f -not -name "Thumbs.db"); do 
    filemd5=$(md5sum $i|awk '{print $1}') 
        [ $? -ne 0 ] && echo $filemd5 && continue
        package_file $project $filemd5 "${i}"
    done
}

check_file_list "test"

# 还原默认的IFS
IFS=$IFS_OLD