Shell test 命令
《Shell test 命令》深度学习版 🧠
🎉 欢迎来到 Shell 编程中极为关键的一章 —— test 命令。它是 Linux 中用于执行条件判断的“大脑”,是 if、while、case 等流程控制语句背后的“逻辑引擎”。掌握它,你就能写出真正智能、自动化的脚本!
🎯 学习目标
- 理解
test命令的本质与作用 - 掌握文件测试、字符串比较、整数比较等各类表达式
- 能在实际脚本中灵活使用
[ ]和[[ ]] - 学会结合
$?和if实现复杂逻辑判断 - 避免常见陷阱和语法错误,写出健壮可靠的 Shell 条件语句
⭐ 核心重点(知识点速览)
| 类型 | 表达式 | 含义 |
|---|---|---|
| 文件测试 | -f, -d, -r, -w, -x, -e |
判断文件是否存在、是否为目录、是否有权限等 |
| 字符串测试 | =, !=, -z, -n |
是否相等、为空、非空 |
| 整数测试 | -eq, -ne, -gt, -lt, -ge, -le |
数值比较 |
| 逻辑运算 | !, -a, -o 或 &&, ` |
|
| 简写形式 | [ expression ] |
POSIX 兼容方式 |
| 扩展形式 | [[ expression ]] |
Bash 扩展,支持更强大语法 |
| 返回值 | $? |
上一个命令的退出状态,0 表示成功/真,非 0 表示失败/假 |
📖 详细讲解
一、什么是 test 命令?
test 是一个内建命令,用于评估一个表达式是否为真(true)或假(false)。它返回一个退出状态码:
- ✅ 0:表示 true(条件成立)
- ❌ 非0:表示 false(条件不成立)
test 5 -gt 3
echo $? # 输出 0,说明 5 > 3 成立
💡 通常我们不会直接使用
test,而是使用它的简写形式:[ expression ]。
二、文件测试(File Test Operators)
这些操作符用于检查文件或目录的状态。
| 表达式 | 描述 |
|---|---|
-f file |
是否为普通文件 |
-d dir |
是否为目录 |
-r file |
是否可读 |
-w file |
是否可写 |
-x file |
是否可执行 |
-e file |
是否存在(不论类型) |
-s file |
是否存在且大小大于 0 |
✅ 示例:
file="/etc/passwd"
if [ -f "$file" ]; then
echo "✅ $file 是一个普通文件"
fi
if [ -r "$file" ]; then
echo "✅ $file 可读"
fi
if [ -w "$file" ]; then
echo "✅ $file 可写"
else
echo "❌ $file 不可写"
fi
三、字符串测试(String Operators)
| 表达式 | 描述 |
|---|---|
str1 = str2 或 str1 == str2 |
是否相等 |
str1 != str2 |
是否不等 |
-z str |
是否为空字符串 |
-n str |
是否非空(注意:变量未赋值时也可能返回 false) |
✅ 示例:
name="Alice"
if [ "$name" = "Alice" ]; then
echo "✅ 用户名正确"
fi
empty=""
if [ -z "$empty" ]; then
echo "✅ 字符串为空"
fi
⚠️ 注意:
- 字符串必须用双引号包裹,避免变量未定义时报错。
- 使用
==是 Bash 支持的扩展,但为了兼容性建议使用=。
四、整数测试(Integer Operators)
只能用于整数之间的比较,不能用于浮点数。
| 表达式 | 描述 |
|---|---|
-eq |
等于 |
-ne |
不等于 |
-gt |
大于 |
-lt |
小于 |
-ge |
大于等于 |
-le |
小于等于 |
✅ 示例:
a=10
b=20
if [ $a -gt $b ]; then
echo "✅ a > b"
elif [ $a -lt $b ]; then
echo "✅ a < b"
else
echo "✅ a = b"
fi
五、布尔逻辑运算符(Logical Operators)
| 运算符 | 描述 | Bash 替代写法 |
|---|---|---|
! |
非 | ! |
-a |
与 | && |
-o |
或 | ` |
✅ 示例:
age=25
if [ $age -ge 18 -a $age -le 60 ]; then
echo "✅ 年龄在合法范围内"
fi
# 更推荐使用 [[ ]] 和 && / ||
if [[ $age -ge 18 && $age -le 60 ]]; then
echo "✅ 年龄在合法范围内"
fi
六、[ ] vs [[ ]]:有什么区别?🔥
| 特性 | [ ] |
[[ ]] |
|---|---|---|
| 是否 Bash 内建 | 是 | 是 |
| 是否支持通配符 | 否 | 是(如 =~ 正则匹配) |
| 是否支持 && || | 否(需用 -a / -o) |
是 |
| 是否需要对变量加引号 | 必须加 | 推荐加 |
| 是否支持字符串模式匹配 | 否 | 是(如 [[ $str == *.log ]]) |
✅ 示例对比:
str="hello world"
# 使用 [ ]
if [ "$str" = "hello world" ]; then
echo "✅ 匹配成功"
fi
# 使用 [[ ]]
if [[ $str == "hello world" ]]; then
echo "✅ 匹配成功"
fi
# 支持通配符匹配
if [[ $str == hello* ]]; then
echo "✅ 以 hello 开头"
fi
# 支持正则匹配
if [[ $str =~ ^h.*d$ ]]; then
echo "✅ 符合正则表达式"
fi
七、实战案例分析 🧪
🎯 场景一:备份脚本 + 条件判断
#!/bin/bash
backup_dir="/home/ubuntu/backups"
src_file="/etc/passwd"
if [ ! -d "$backup_dir" ]; then
mkdir -p "$backup_dir"
echo "📁 备份目录已创建"
fi
if [ -f "$src_file" ]; then
cp "$src_file" "$backup_dir/passwd_$(date +%Y%m%d).bak"
echo "✅ 已备份 passwd 文件"
else
echo "❌ 错误:源文件不存在"
exit 1
fi
🎯 场景二:日志清理脚本 + 文件大小判断
logfile="/var/log/app.log"
if [ -f "$logfile" ]; then
size=$(du -k "$logfile" | awk '{print $1}')
if [ $size -gt 1024 ]; then # 如果日志超过 1MB
echo "🗑️ 日志过大,正在清理..."
> "$logfile"
else
echo "✅ 日志正常,无需清理"
fi
else
echo "⚠️ 日志文件不存在"
fi
🎯 场景三:用户登录验证脚本
read -p "请输入用户名:" username
read -sp "请输入密码:" password
valid_user="admin"
valid_pass="123456"
if [ "$username" = "$valid_user" ] && [ "$password" = "$valid_pass" ]; then
echo -e "\n✅ 登录成功!欢迎 $username"
else
echo -e "\n❌ 登录失败,请重试"
fi
⚠️ 常见陷阱 & 解决方案
| 问题 | 原因 | 解决方法 |
|---|---|---|
[: unary operator expected |
变量未赋值或为空 | 使用双引号 " " 包裹变量 |
integer expression expected |
比较字符串而非整数 | 使用 -eq 之前确保变量为数字 |
unexpected operator |
使用了 > < 等符号 |
应使用 -gt -lt 等 |
[[ 报错 |
系统 shell 不是 bash | 确保脚本开头为 #!/bin/bash |
| 文件路径含空格 | 未加引号导致解析错误 | 始终用双引号包裹路径变量 |
🧠 总结与小贴士
| 技巧 | 说明 |
|---|---|
test 是 Shell 的“逻辑引擎” |
控制脚本走向的核心工具 |
推荐使用 [[ ]] |
更安全、功能更强 |
| 始终对变量加双引号 | 防止未定义或含空格出错 |
使用 $? 检查结果 |
调试时非常有用 |
结合 if, while 构建复杂逻辑 |
让脚本具备“思考能力” |
| 善用正则匹配和通配符 | 提升灵活性 |
避免直接使用 test 命令 |
推荐使用 [ ] 或 [[ ]] |
📚 推荐练习题(可选)
- 编写一个脚本,判断某个服务(如 nginx)是否运行,如果没有就启动它。
- 写一个脚本,检查
/tmp目录下是否有.tmp文件,如果有则删除。 - 实现一个简易计算器,接收两个参数和一个运算符(+、-、*、/),输出结果。
- 编写一个脚本,判断当前用户是否为 root,不是则提示并退出。
- 创建一个日志分析脚本,统计某日志中包含 “error” 的行数。
🎯 下一章预告:《Shell 流程控制 —— if、for、while、until》
你已经掌握了如何进行条件判断,下一步我们将学习如何根据这些判断来控制脚本的执行流程 —— 使用 if, for, while, until 等流程控制语句,让你的脚本真正“动起来”!
需要我继续为你生成下一章内容吗?😊

浙公网安备 33010602011771号