我使用以下脚本来查看文件是否存在:
#!/bin/bash
FILE=$1
if [ -f $FILE ]; then
echo "File $FILE exists."
else
echo "File $FILE does not exist."
fi
如果我只想检查文件是否正确,那么使用的语法是什么 不 存在?
#!/bin/bash
FILE=$1
if [ $FILE does not exist ]; then
echo "File $FILE does not exist."
fi
该 测试 命令([
这里有一个“非”逻辑运算符,它是感叹号(类似于许多其他语言)。尝试这个:
if [ ! -f /tmp/foo.txt ]; then
echo "File not found!"
fi
Bash文件测试
-b filename
- 阻止特殊文件
-c filename
- 特殊字符文件
-d directoryname
- 检查目录是否存在
-e filename
- 检查文件是否存在,无论类型(节点,目录,套接字等)
-f filename
- 检查常规文件是否存在而不是目录
-G filename
- 检查文件是否存在并由有效组ID拥有
-G filename set-group-id
- 如果文件存在且为set-group-id,则为True
-k filename
- 粘性
-L filename
- 符号链接
-O filename
- 如果文件存在且为有效用户ID所有,则为True
-r filename
- 检查文件是否可读
-S filename
- 检查文件是否为套接字
-s filename
- 检查文件是否为非零大小
-u filename
- 检查文件set-user-id位是否已设置
-w filename
- 检查文件是否可写
-x filename
- 检查文件是否可执行
如何使用:
#!/bin/bash
file=./file
if [ -e "$file" ]; then
echo "File exists"
else
echo "File does not exist"
fi
一个 测试表达 可以通过使用来否定 !
操作者
#!/bin/bash
file=./file
if [ ! -e "$file" ]; then
echo "File does not exist"
else
echo "File exists"
fi
你可以用“!”来否定表达式:
#!/bin/bash
FILE=$1
if [ ! -f "$FILE" ]
then
echo "File $FILE does not exist"
fi
相关的手册页是 man test
或者,等效地, man [
- 要么 help test
要么 help [
用于内置bash命令。
[[ -f $FILE ]] || printf '%s does not exist!\n' "$FILE"
此外,文件可能是破碎的符号链接,或非常规文件,例如,套接字,设备或fifo。例如,要添加对损坏的符号链接的检查:
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
值得一提的是,如果你需要执行一个命令,你可以缩写
if [ ! -f "$file" ]; then
echo "$file"
fi
至
test -f "$file" || echo "$file"
要么
[ -f "$file" ] || echo "$file"
我更喜欢做以下单行,在 POSIX shell兼容格式:
$ [ -f "/$DIR/$FILE" ] || echo "$FILE NOT FOUND"
$ [ -f "/$DIR/$FILE" ] && echo "$FILE FOUND"
对于一些命令,就像我在脚本中所做的那样:
$ [ -f "/$DIR/$FILE" ] || { echo "$FILE NOT FOUND" ; exit 1 ;}
一旦我开始这样做,我很少再使用完全类型化的语法!
要测试文件是否存在,参数可以是以下任何一个:
-e: Returns true if file exists (regular file, directory, or symlink)
-f: Returns true if file exists and is a regular file
-d: Returns true if file exists and is a directory
-h: Returns true if file exists and is a symlink
以下所有测试都适用于常规文件,目录和符号链接:
-r: Returns true if file exists and is readable
-w: Returns true if file exists and is writable
-x: Returns true if file exists and is executable
-s: Returns true if file exists and has a size > 0
示例脚本:
#!/bin/bash
FILE=$1
if [ -f "$FILE" ]; then
echo "File $FILE exists"
else
echo "File $FILE does not exist"
fi
你应该小心跑步 test
对于未加引号的变量,因为它可能会产生意外的结果:
$ [ -f ]
$ echo $?
0
$ [ -f "" ]
$ echo $?
1
建议通常是让测试变量用双引号括起来:
#!/bin/sh
FILE=$1
if [ ! -f "$FILE" ]
then
echo "File $FILE does not exist."
fi
你可以这样做:
[[ ! -f "$FILE" ]] && echo "File doesn't exist"
要么
if [[ ! -f "$FILE" ]]; then
echo "File doesn't exist"
fi
如果要同时检查文件和文件夹,请使用 -e
选项而不是 -f
。 -e
对常规文件,目录,套接字,字符特殊文件,块特殊文件等返回true。
在
[ -f "$file" ]
该 [
命令做了 stat()
(不 lstat()
)系统调用存储在路径中 $file
并返回 真正 如果该系统调用成功并且返回的文件类型 stat()
是“正常的”。
因此,如果 [ -f "$file" ]
返回true,你可以告诉文件确实存在并且是一个常规文件或符号链接最终解析为一个常规文件(或者至少它是在 stat()
)。
但是如果它返回 假 (或者如果 [ ! -f "$file" ]
要么 ! [ -f "$file" ]
返回true),有许多不同的可能性:
- 该文件不存在
- 该文件存在但不是常规文件
- 该文件存在,但您没有父目录的搜索权限
- 该文件存在,但访问它的路径太长
- 该文件是常规文件的符号链接,但您没有对符号链接解析中涉及的某些目录的搜索权限。
- ......任何其他原因
stat()
系统调用可能会失败。
简而言之,它应该是:
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
要确定该文件不存在,我们需要 stat()
系统调用返回错误代码为 ENOENT
(ENOTDIR
告诉我们其中一个路径组件不是目录是另一种情况,我们可以通过该路径告诉该文件不存在)。不幸的是 [
命令不让我们知道。无论错误代码是ENOENT,EACCESS(权限被拒绝),ENAMETOOLONG还是其他任何内容,它都将返回false。
该 [ -e "$file" ]
测试也可以用 ls -Ld -- "$file" > /dev/null
。在这种情况下, ls
会告诉你为什么 stat()
失败了,虽然信息不能以编程方式轻松使用:
$ file=/var/spool/cron/crontabs/root
$ if [ ! -e "$file" ]; then echo does not exist; fi
does not exist
$ if ! ls -Ld -- "$file" > /dev/null; then echo stat failed; fi
ls: cannot access '/var/spool/cron/crontabs/root': Permission denied
stat failed
至少 ls
告诉我这不是因为文件不存在而失败了。这是因为它无法判断文件是否存在。该 [
命令只是忽略了问题。
随着 zsh
shell,您可以使用查询错误代码 $ERRNO
失败后的特殊变量 [
命令,并使用。解码该号码 $errnos
中的特殊数组 zsh/system
模块:
zmodload zsh/system
ERRNO=0
if [ ! -f "$file" ]; then
err=$ERRNO
case $errnos[err] in
("") echo exists, not a regular file;;
(ENOENT|ENOTDIR)
if [ -L "$file" ]; then
echo broken link
else
echo does not exist
fi;;
(*) echo "can't tell"; syserror "$err"
esac
fi
(小心 $errnos
某些版本的支持被破坏了 zsh
当使用最新版本构建时 gcc
)。