安全引用含空格文本需在定义、传递、展开三环节全程用引号守护:定义时用"hello world",引用时用"$msg",遍历文件名须用find -print0 | while read -r -d ''。

安全引用含空格的文本,核心不是“怎么加引号”,而是**在变量定义、传递、展开三个环节都守住边界**——漏掉任一环,空格就会被当作分词符切开。
定义时必须用引号包裹值
未加引号的赋值会触发即时分词,空格后的内容直接变成新命令:
-
错误写法:
msg=hello world→ shell 将world当作独立命令执行,报错bash: world: command not found -
正确写法:
msg="hello world"或msg='hello world'—— 单双引号均可,但双引号支持变量展开,更常用 - 若值来自命令替换,也需包裹:
files="$(find /tmp -name '*.log' -print0)"(注意:这里只是暂存,后续仍需按 null 分隔处理)
引用时必须用双引号包住变量展开
即使定义时加了引号,引用时不加引号,空格依然会被切开:
-
危险写法:
echo $msg→ 输出变成两段参数,可能破坏命令语义(如cp $msg /dest会误判为多参数) -
安全写法:
echo "$msg"—— 双引号确保整个字符串作为单个参数传递 - 拼接使用也一样:
echo "Result: $msg"或更严谨的echo "Result: ${msg}"
遍历含空格文件名?别用 for 循环直接展开
这是最常踩的坑。无论变量定义多规范,for f in $files 或 for f in $(ls) 都会经过 IFS 分词,天然不安全:
- ❌
for f in $(find . -name "*.txt"); do echo "$f"; done—— 遇到my file.txt会被拆成my和file.txt - ✅ 正确方式是用
find -print0 | while read -r -d '':
其中 -d '' 指定 null 字节分隔,IFS= 防止首尾空白被裁剪,-r 禁用反斜杠转义——三者缺一不可。
特殊情况:需要按行处理文本(非文件名)
如果明确处理的是自己生成的、仅含换行不含空格/制表符的纯文本列表,可临时调整 IFS:
- 先备份:
old_ifs=$IFS - 设为换行:
IFS=$'\n' - 再展开:
for line in $text_list; do ...; done - 最后恢复:
IFS=$old_ifs
但注意:此法不适用于文件名或用户输入——因为换行本身也是合法文件名字符,只有 \0 是绝对安全的分隔符。











