这将检查文件是否存在:
#!/bin/bash
FILE=$1
if [ -f $FILE ]; then
echo "File $FILE exists."
else
echo "File $FILE does not exist."
fi
我如何只检查文件是否不存在?
if [ -f $FILE ]; then; else; echo "File $FILE does not exist."; fi;
我发现这个问题并学会以更正确的方式来做这件事可能很好。 :)
-e
。 -f 不会选择目录、符号链接等。
FILE=$1
->; FILE="$1"
和 if [ -f $FILE ];
-> if [ -f "$FILE" ];
Bash 文件测试
-b filename
- 阻止特殊文件
-c filename
- 特殊字符文件
-d directoryname
- 检查目录是否存在
-e filename
- 检查文件是否存在,无论类型如何(节点、目录、套接字、等)
-f filename
- 检查常规文件是否存在而不是目录
-G filename
- 检查文件是否存在并由有效组 ID 拥有
-G filename set-group-id
- 如果文件存在且已设置则为真-group-id
-k filename
- 粘滞位
-L filename
- 符号链接
-O filename
- 如果文件存在并且由有效用户 ID 拥有,则为真
-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
-n String
- 检查字符串的长度是否不为零。还是您的意思是 file1 -nt file2
- 检查文件 1 是否比文件 2 新(您也可以使用 -ot 表示较旧的)
The unary operator -z tests for a null string, while -n or no operator at all returns True if a string is not empty.
~ ibm.com/developerworks/library/l-bash-test/index.html
file
,然后使用该 file
变量执行其他看起来比使用未知参数 $1
更具可读性的事情
-G
运算符,据我了解,两者略有不同。通过 chmod
手册页的“SETUID & SETGID BITS”部分,两者在 root 用户的情况下会给出不同的值,不是吗?我专门指的是“除非用户具有适当的权限”部分。无论如何,出色的答案。仅为此添加书签。
使用 !
否定 test
内的表达式([
是别名):
#!/bin/bash
FILE=$1
if [ ! -f "$FILE" ]
then
echo "File $FILE does not exist"
fi
对于内置 bash 命令,相关的手册页是 man test
或等效的 man [
-- 或 help test
或 help [
。
或者(不太常用)您可以使用以下命令否定 test
的结果:
if ! [ -f "$FILE" ]
then
echo "File $FILE does not exist"
fi
该语法在“管道”和“复合命令”部分的“man 1 bash”中进行了描述。
[
是内置的。所以相关信息宁可通过 help [
获得...但这表明 [
是 test
内置函数的同义词,因此相关信息宁可通过 help test
获得。另见Bash Conditional Expression section in the manual。
[
命令的行为与外部 [
命令非常相似,因此 man test
或 man [
可以让您很好地了解它的工作原理。
[
具有比我系统上的外部命令 [
更多的开关...一般来说,我认为最好阅读特定于给定工具的文档,而不是特定于另一个模糊相关的文档。我可能错了,虽然;)
[[ -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 ;}
一旦我开始这样做,我就很少再使用完全类型化的语法了!!
[
或 test
内置默认情况下会测试参数的 file 存在(相反-e
)?这不会模棱两可吗? AFAIK(和 AIUI 的“条件表达式”部分)唯一用您的方法测试的是参数不为空(或未定义),在这种情况下,这是一个重言式(让 $DIR = ''
和 $FILE = ''
, 那么参数仍然是 '//'
)。
ls /foo
,结果 ls: cannot access /foo: No such file or directory
。 [ /foo ] && echo 42
,结果 42
。 GNU bash,版本 4.2.37(1)-release (i486-pc-linux-gnu)。
-f
选项。显然,如果您不确定它是否是常规文件,您总是可以使用 -e
。此外,在我所有的脚本中,我都引用了这些结构,我一定只是在没有充分校对的情况下提交了这个。
[ $condition ] && if_true || if_false
容易出错。无论如何,我发现 [ ! -f "$file" ] && if_not_exists
比 [ -f "$file" ] || if_not_exists
更容易阅读和理解。
测试文件是否存在,参数可以是以下任意一种:
-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
你可以这样做:
[[ ! -f "$FILE" ]] && echo "File doesn't exist"
或者
if [[ ! -f "$FILE" ]]; then
echo "File doesn't exist"
fi
如果您想同时检查文件和文件夹,请使用 -e
选项而不是 -f
。 -e
对常规文件、目录、套接字、字符特殊文件、块特殊文件等返回 true。
[
实用程序相比,它的优势有限。
-f
检查)和目录只是许多不同类型的文件中的两种。还有套接字、符号链接、设备、fifos、门... [ -e
将测试文件是否存在(任何类型,包括常规、fifo、目录...)在符号链接解析后。
-e
,他需要 -f
。
您应该小心为未引用的变量运行 test
,因为它可能会产生意想不到的结果:
$ [ -f ]
$ echo $?
0
$ [ -f "" ]
$ echo $?
1
建议通常是将测试变量用双引号括起来:
#!/bin/sh
FILE=$1
if [ ! -f "$FILE" ]
then
echo "File $FILE does not exist."
fi
[ ... ]
。
在
[ -f "$file" ]
[
命令对存储在 $file
中的路径执行 stat()
(不是 lstat()
)系统调用,如果该系统调用成功并且返回的文件类型为stat()
是“常规”。
因此,如果 [ -f "$file" ]
返回 true,您可以判断该文件确实存在并且是常规文件或最终解析为常规文件的符号链接(或至少在 stat()
时)。
但是,如果它返回 false(或者如果 [ ! -f "$file" ]
或 ! [ -f "$file" ]
返回 true),则有许多不同的可能性:
该文件不存在
该文件存在但不是常规文件(可能是设备、fifo、目录、套接字...)
该文件存在,但您没有父目录的搜索权限
该文件存在,但访问它的路径太长
该文件是指向常规文件的符号链接,但您对解析符号链接所涉及的某些目录没有搜索权限。
... 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
特殊变量查询错误代码,并使用 zsh/system
模块中的 $errnos
特殊数组解码该数字:
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;;
(*) syserror -p "can't tell: " "$err"
esac
fi
(注意 $errnos
support was broken with some versions of zsh
when built with recent versions of gcc
)。
有三种不同的方法可以做到这一点:
用 bash 否定退出状态(没有其他答案这么说):如果! [ -e "$file" ];然后回显“文件不存在” fi 或:! [ -e "$file" ] && echo "file does not exist" 在测试命令 [ 中否定测试(这是之前大多数答案的呈现方式): if [ ! -e "$文件" ];然后回显“文件不存在” fi 或:[! -e "$file" ] && echo "file does not exist" 对测试结果是否定的(|| 代替 &&)进行处理:仅: [ -e "$file" ] || echo "file does not exist" 这看起来很傻(IMO),除非您的代码必须可移植到缺少管道否定运算符的 Bourne shell(如 Solaris 10 或更早版本的 /bin/sh),否则不要使用它( !): if [ -e "$file" ];然后:否则回显“文件不存在”fi
! [
和 [ !
之间的可移植性有何不同?
! [
is POSIX for shell pipelines 2.9.2 (any command) Otherwise, the exit status shall be the logical NOT of the exit status of the last command
和 [ !
is POSIX for test ! expression True if expression is false. False if expression is true.
因此,它们都是 POSIX,并且根据我的经验,它们都得到了广泛的支持。
!
关键字。不过,除了 Solaris 10 和更早版本,您现在不太可能遇到 Bourne shell。
envfile=.env
if [ ! -f "$envfile" ]
then
echo "$envfile does not exist"
exit 1
fi
要反转测试,请使用“!”。这相当于其他语言中的“非”逻辑运算符。尝试这个:
if [ ! -f /tmp/foo.txt ];
then
echo "File not found!"
fi
或者用稍微不同的方式写:
if [ ! -f /tmp/foo.txt ]
then echo "File not found!"
fi
或者你可以使用:
if ! [ -f /tmp/foo.txt ]
then echo "File not found!"
fi
或者,一起按下:
if ! [ -f /tmp/foo.txt ]; then echo "File not found!"; fi
可以写成(然后使用“and”运算符:&&):
[ ! -f /tmp/foo.txt ] && echo "File not found!"
看起来像这样更短:
[ -f /tmp/foo.txt ] || echo "File not found!"
test
的事情也可能算数。它对我有用(基于 Bash Shell: Check File Exists or Not):
test -e FILENAME && echo "File exists" || echo "File doesn't exist"
test
也可以算数。”:它算什么?
此代码也有效。
#!/bin/bash
FILE=$1
if [ -f $FILE ]; then
echo "File '$FILE' Exists"
else
echo "The File '$FILE' Does Not Exist"
fi
最简单的方法
FILE=$1
[ ! -e "${FILE}" ] && echo "does not exist" || echo "exists"
此 shell 脚本也适用于在目录中查找文件:
echo "enter file"
read -r a
if [ -s /home/trainee02/"$a" ]
then
echo "yes. file is there."
else
echo "sorry. file is not there."
fi
read -p "Enter file name: " -r a
来提示和阅读。它确实在变量周围使用引号;这很好,但应该解释一下。如果它回显文件名可能会更好。这将检查文件是否存在且不为空(这就是 -s
的含义),而问题询问任何文件,无论是否为空(对于哪个 -f
更合适)。
有时使用 && 和 || 可能很方便运营商。
就像在(如果你有命令“测试”):
test -b $FILE && echo File not there!
或者
test -b $FILE || echo File there!
如果您想使用 test
而不是 []
,那么您可以使用 !
来获得否定:
if ! test "$FILE"; then
echo "does not exist"
fi
[
,您也可以使用 !
!
您还可以将多个命令组合在一个衬垫中
[ -f "filename" ] || ( echo test1 && echo test2 && echo test3 )
或者
[ -f "filename" ] || { echo test1 && echo test2 && echo test3 ;}
如果文件名没有退出,输出将是
test1
test2
test3
Note: ( ... ) 在子 shell 中运行,{ ... ;} 在同一个 shell 中运行。
if [ ! \( -f "f1" -a -f "f2" \) ] ; then echo MISSING; fi
if [ ! -f "f1" ] || [ ! -f "f2" ] ; then echo MISSING; fi
[ -f /tmp/foo.txt ] || echo "File not found!"
-e: Returns true value, if file exists
-f: Return true value, if file exists and regular file
-r: Return true value, if file exists and is readable
-w: Return true value, if file exists and is writable
-x: Return true value, if file exists and is executable
-d: Return true value, if exists and is a directory
! -f
与&&
一起使用与将-f
与||
一起使用存在不对称性。这与不/存在检查返回的退出代码有关。如果您需要您的线路始终以退出代码 0 干净地退出(有时您不希望此约束),则这两种方法不可互换。或者,只需使用if
语句,您就不必再担心不/存在检查的退出代码。