在Bash中判断文件是否不存在

在Bash中判断文件是否不存在

技术背景

在Bash脚本编程中,经常需要判断文件是否存在。比如在脚本执行前,需要检查配置文件是否存在,若不存在则进行相应的处理。了解如何准确判断文件是否不存在是编写健壮脚本的重要技能。

实现步骤

使用 test 命令的否定逻辑

test 命令(通常简写为 [)有一个 “非” 逻辑运算符 !(感叹号)。以下是判断文件 /tmp/foo.txt 是否不存在的示例:

1
2
3
if [ ! -f /tmp/foo.txt ]; then
echo "File not found!"
fi

不同文件测试选项

Bash 提供了多种文件测试选项,常用的如下:

  • -e filename:检查文件是否存在,无论文件类型(节点、目录、套接字、符号链接等)。
  • -f filename:检查普通文件是否存在,而不是目录。

使用否定运算符判断文件不存在

1
2
3
4
5
6
7
#!/bin/bash
file=./file
if [ ! -e "$file" ]; then
echo "File does not exist"
else
echo "File exists"
fi

核心代码

示例代码 1

1
2
3
4
5
#!/bin/bash
FILE=$1
if [ ! -f "$FILE" ]; then
echo "File $FILE does not exist"
fi

示例代码 2

1
2
3
#!/bin/bash
file=./file
test -f "$file" || echo "$file"

示例代码 3

1
2
3
4
5
6
7
8
9
#!/bin/bash
FILE=$1
if [[ ! -f "$FILE" ]]; then
if [[ -L "$FILE" ]]; then
printf '%s is a broken symlink!\n' "$FILE"
else
printf '%s does not exist!\n' "$FILE"
fi
fi

最佳实践

使用引号包围变量

为避免因变量未加引号而产生意外结果,建议将测试的变量用双引号包围:

1
2
3
4
5
#!/bin/sh
FILE=$1
if [ ! -f "$FILE" ]; then
echo "File $FILE does not exist."
fi

多种判断方式结合

为了更准确地判断文件情况,可以结合多种判断方式:

1
2
3
4
5
6
7
8
9
if [ -f "$file" ]; then
printf '"%s" is a path to a regular file or symlink to regular file\n' "$file"
elif [ -e "$file" ]; then
printf '"%s" exists but is not a regular file\n' "$file"
elif [ -L "$file" ]; then
printf '"%s" exists, is a symlink but I cannot tell if it eventually resolves to an actual file, regular or not\n' "$file"
else
printf 'I cannot tell if "%s" exists, let alone whether it is a regular file or not\n' "$file"
fi

常见问题

变量未加引号导致意外结果

如果在 test 中使用未加引号的变量,可能会产生意外结果:

1
2
3
4
5
6
$ [ -f ]
$ echo $?
0
$ [ -f "" ]
$ echo $?
1

stat() 系统调用失败的多种情况

[ -f "$file" ] 返回 false 时,有多种可能:

  • 文件不存在。
  • 文件存在但不是普通文件(可能是设备、命名管道、目录、套接字等)。
  • 文件存在但没有对其父目录的搜索权限。
  • 文件存在但访问路径太长。
  • 文件是指向普通文件的符号链接,但在解析符号链接时没有对某些目录的搜索权限。
  • 其他导致 stat() 系统调用失败的原因。

不同 shell 对错误代码的处理

zsh 中,可以使用 $ERRNO 特殊变量查询失败的 [ 命令后的错误代码,并使用 zsh/system 模块中的 $errnos 特殊数组解码该数字,但某些版本的 zsh 在使用最新版本的 gcc 编译时,$errnos 支持可能会出现问题。


在Bash中判断文件是否不存在
https://119291.xyz/posts/2025-05-09.judge-file-existence-in-bash/
作者
ww
发布于
2025年5月9日
许可协议