核心是始终用双引号包裹变量引用,否则Shell按IFS拆分导致文件名断裂;定义可不加引号,但调用、传参、循环、命令替换中必须加引号,禁用$(ls),优先用glob或find -print0/xargs -0处理含空格文件名。

Shell变量处理含空格的文件名,核心就一条:**始终用双引号包裹变量引用**。不加引号,Shell会按IFS(默认含空格、制表符、换行符)自动拆分,导致一个文件名变成多个参数。
变量定义和引用必须加双引号
定义时带空格没问题,但调用时必须保护:
-
错误写法:
file=my document.txt; cp $file /tmp→ 实际执行cp my document.txt /tmp,报错“no such file” -
正确写法:
file="my document.txt"; cp "$file" /tmp→ 完整传递为单个参数
函数传参也要全程加引号
不仅调用函数时要引号,函数内部使用参数时也得引号:
- 调用:
process_file "$target_dir" - 函数内:
for f in "$1"/*.log; do echo "$f"; done(注意"$1"/*不能写成$1/*)
避免用$(ls)或反引号展开
这类命令替换会触发单词拆分,极不可靠:
- 不要写:
for f in $(ls *.txt); do ... - 改用通配符直接展开:
for f in *.txt; do echo "$f"; done(前提是当前目录有匹配项) - 或用
find配合-print0:find . -name "*.txt" -print0 | while IFS= read -r -d '' f; do echo "$f"; done
需要批量处理时优先用find + xargs -0
这是处理任意文件名(含空格、换行、特殊字符)最稳妥的方式:
find . -type f -name "*.log" -print0 | xargs -0 gzipfind /data -name "report *" -print0 | xargs -0 -I {} mv {} /archive/- 关键点:
-print0让find用\0分隔,xargs -0识别该分隔符,彻底绕过空格问题

















