linux shell 编程:文件判断详细解释 作者:马育民 • 2026-09-25 08:28 • 阅读:10001 # 介绍 Shell 中文件判断有三种写法: 1. `test 表达式` 2. `[ 表达式 ]` (`[` 就是 test 命令,**左右必须空格**) 3. `[[ 表达式 ]]` (Bash 扩展,更安全,推荐,支持正则,**左右也要空格**) # 语法 ### 写法1 ```bash test -f /etc/passwd ``` ### 写法2(常用) ``` if [ -f /etc/passwd ]; then echo "是普通文件" fi ``` ### 写法3 bash推荐 ``` if [[ -f /etc/passwd ]]; then echo "是普通文件" fi ``` # 文件类型判断 | 参数 | 含义 | |---|---| | `-e file` | **exists**:文件/目录是否存在(不管是什么类型)✅最通用 | | `-f file` | **file**:存在且是**普通文件**(不是目录、链接、设备) | | `-d file` | **directory**:存在且是**目录** | | `-L file` / `-h file` | **link**:存在且是**软链接**(符号链接) | | `-b file` | **block**:块设备文件(硬盘、U盘) | | `-c file` | **character**:字符设备(终端 /dev/tty) | | `-p file` | 命名管道(FIFO) | | `-S file` | **socket**:套接字文件 | **注意:**`-f /tmp/link` 如果是软链接指向普通文件,**`-f` 会跟随链接**;`-L` 只判断本身是不是链接。 # 文件权限判断 | 参数 | 含义 | |---|---| | `-r file` | 当前用户**可读** | | `-w file` | 当前用户**可写** | | `-x file` | 当前用户**可执行** | | `-u file` | 文件有SUID权限(set-user-id) | | `-g file` | 文件有SGID权限(set-group-id) | | `-k file` | 文件有粘滞位sticky bit(如/tmp目录) | > 注意:权限判断是**进程当前用户身份**,不是看文件权限字符串字面量。 # 文件大小判断 | 参数 | 含义 | |---|---| | `-s file` | 文件存在**且大小 > 0**(非空文件) | | `-z 字符串` | 字符串为空(**不是文件大小!** 容易混淆) | | `-n 字符串` | 字符串非空 | > 示例:`[ -s log.txt ]` 日志文件不为空 # 两个文件之间比较 二元判断 ```bash [ file1 -nt file2 ] ``` | 参数 | 含义 | |---|---| | `file1 -nt file2` | new than:file1 比 file2 **更新**(修改时间mtime) | | `file1 -ot file2` | old than:file1 比 file2 **更旧** | | `file1 -ef file2` | equal file:两个文件**inode相同**(硬链接,指向同一个文件) | # 逻辑组合(与/或/非) ### `[ ]` / test 中用 `-a` `-o` `!` ```bash ! [ -f a.txt ] # 取反:不是普通文件 [ -f a.txt -a -r a.txt ] # -a 逻辑与,文件存在且可读 [ -d dir -o -f file ] # -o 逻辑或 ``` > ⚠️ `-a / -o` 在 `[ ]` 里有歧义,**不推荐** ### `[[ ]]` 推荐用 `&&` `||` `!` ```bash if [[ -f "a.txt" && -r "a.txt" ]]; then echo "存在并且可读" fi ``` - `!` 取反 - `&&` 逻辑与 - `||` 逻辑或 # 常见坑(重点) ### 1. **`[ ]` 两边必须空格** ```bash [ -f test.txt ] ✅ [-f test.txt ] ❌ 报错! ``` ### 2. **变量不加引号,文件名带空格会炸** ```bash file="my file.txt" [ -f $file ] # 错误,空格会截断 [ -f "$file" ] # 正确,加双引号 [[ -f $file ]] # bash [[ ]] 内部自动处理,不加引号一般也安全,但建议养成加引号习惯 ``` ### 3. `-e` 和 `-f` 区别 - `-e`:只要存在就返回真(目录也会true) - `-f`:必须是普通文件 ### 4. 软链接: - `-f`、`-d`、`-r` **跟随软链接,判断链接指向的目标** - `-L` 只判断**本身是不是链接**,不跟进目标 # 例子 ```bash #!/bin/bash path="./test.txt" if [[ ! -e "$path" ]]; then echo "文件不存在" elif [[ -f "$path" ]]; then echo "是普通文件" if [[ -r "$path" ]]; then echo "可读" fi if [[ -s "$path" ]]; then echo "文件非空" fi elif [[ -d "$path" ]]; then echo "这是目录" fi ``` # 总结 ``` -e 存在 -f 普通文件 -d 目录 -L 软链接 -r 可读 -w 可写 -x 可执行 -s 文件>0字节 -nt 更新 -ot 更旧 -ef 同一inode(硬链接) ! 非 &&与 ||或 ``` 原文出处:/show_1GW46uznYvPo.html