LabHub
学习 学习路径 课程

Shell 脚本

少写引号会发生什么

在 LabHub 中继续学习

一句话总结

Shell 在变量展开后进行分词。不加引号会把一个值变成多个参数,使脚本执行完全不同的操作。

概念图: 一句话总结 · 安全传参 · 原文命令与标识符

安全传参

变量、数组和脚本参数都必须保留原有边界。文件名可以包含空格甚至换行,因此文件列表应使用 NUL 分隔,或直接让 find 执行动作。命令的双横线用于结束选项解析,避免以连字符开头的文件名被当成选项。

短选项应交给 getopts,而不是手写脆弱的解析器。用户输入只能作为值传给命令,绝不能交给 eval 重新解释;路径也必须验证不能越出预期目录。ShellCheck 能检查常见引号、read 和无用管道问题。

原文命令与标识符

OLD=$(find /data -name '*.tmp' -mtime +7)
rm $OLD
f="my report.txt"
rm $f      # rm my report.txt   → 인자 2개
rm "$f"    # rm "my report.txt" → 인자 1개 ✅
args=(-l -a "my dir")
ls "${args[@]}"    # 각 원소가 하나의 인자로 ✅
ls ${args[@]}      # 다시 쪼개진다 ✗
# 안전
find /data -name '*.tmp' -mtime +7 -print0 | xargs -0 rm --

# 더 안전 (xargs 도 필요 없다)
find /data -name '*.tmp' -mtime +7 -delete

# 루프가 필요하면
while IFS= read -r -d '' f; do
  process "$f"
done < <(find /data -name '*.tmp' -print0)
rm -- "$f"
grep -- "$pattern" "$file"
verbose=0; out=""
while getopts ":vo:" opt; do
  case $opt in
    v) verbose=1 ;;
    o) out=$OPTARG ;;
    :) echo "-$OPTARG 에 값이 필요합니다" >&2; exit 2 ;;
    \?) echo "알 수 없는 옵션: -$OPTARG" >&2; exit 2 ;;
  esac
done
shift $((OPTIND - 1))
# 남은 것이 위치 인자
# 절대 금지
eval "grep $user_input file.txt"

# 값으로만 쓴다
grep -- "$user_input" file.txt

/data/my report.tmp

rm

/data/my

report.tmp

/data/my

"$@"

"$*"

"$@"

"$*"

"$@"

IFS= read -r

IFS=

-r

--

-rf

rm $file

--

$1

case

getopts

":vo:"

:

\?

eval

; rm -rf /

../../etc/passwd

shellcheck

read

-r

cat

"$@"

$*

getopts

-vo

eval