如何判断Bash中是否存在文件?

这将检查文件是否存在:

#!/bin/bash
FILE=$1if [ -f $FILE ]; thenecho "File $FILE exists."elseecho "File $FILE does not exist."fi

如何仅检查文件是否存在没有

2932999 次浏览

#0命令(这里写成[)有一个“not”逻辑运算符,!(感叹号):

if [ ! -f /tmp/foo.txt ]; thenecho "File not found!"fi

使用!否定test中的表达式(其中[是别名):

#!/bin/bashFILE=$1
if [ ! -f "$FILE" ]thenecho "File $FILE does not exist"fi

对于内置的bash命令,相关的手册页是man testman [--或help testhelp [

或者(不太常用),您可以使用以下方法否定test的结果:

if ! [ -f "$FILE" ]thenecho "File $FILE does not exist"fi

该语法在“man 1 bash”中的“管道”和“复合命令”部分中进行了描述。

[[ -f $FILE ]] || printf '%s does not exist!\n' "$FILE"

此外,该文件可能是一个损坏的符号链接,或者是非常规文件,例如套接字、设备或FIFO。例如,要添加断开的符号链接的检查:

if [[ ! -f $FILE ]]; thenif [[ -L $FILE ]]; thenprintf '%s is a broken symlink!\n' "$FILE"elseprintf '%s does not exist!\n' "$FILE"fifi

值得一提的是,如果您需要执行单个命令,您可以缩写

if [ ! -f "$file" ]; thenecho "$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,因为它可能会产生意想不到的结果:

$ [ -f ]$ echo $?0$ [ -f "" ]$ echo $?1

建议通常是将测试变量用双引号括起来:

#!/bin/shFILE=$1
if [ ! -f "$FILE" ]thenecho "File $FILE does not exist."fi

test也可以算。它对我有效(基于Bash Shell:检查文件是否存在):

test -e FILENAME && echo "File exists" || echo "File doesn't exist"

要反转测试,请使用“!”。这相当于其他语言中的“not”逻辑运算符。试试这个:

if [ ! -f /tmp/foo.txt ];thenecho "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!"

这个外壳脚本也适用于在目录中查找文件:

echo "enter file"
read -r a
if [ -s /home/trainee02/"$a" ]thenecho "yes. file is there."elseecho "sorry. file is not there."fi

要测试文件是否存在,参数可以是以下任意一项:

-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/bashFILE=$1
if [ -f "$FILE" ]; thenecho "File $FILE exists"elseecho "File $FILE does not exist"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/bashfile=./fileif [ -e "$file" ]; thenecho "File exists"elseecho "File does not exist"fi

可以使用!运算符来否定测试表达式

#!/bin/bashfile=./fileif [ ! -e "$file" ]; thenecho "File does not exist"elseecho "File exists"fi

最简单的方法

FILE=$1[ ! -e "${FILE}" ] && echo "does not exist" || echo "exists"

你可以这样做:

[[ ! -f "$FILE" ]] && echo "File doesn't exist"

if [[ ! -f "$FILE" ]]; thenecho "File doesn't exist"fi

如果您想同时检查文件和文件夹,请使用-e选项而不是-f-e对常规文件、目录、套接字、字符特殊文件、阻止特殊文件等返回true。

此代码也有效。

#!/bin/bashFILE=$1if [ -f $FILE ]; thenecho "File '$FILE' Exists"elseecho "The File '$FILE' Does Not Exist"fi

有三种不同的方法可以做到这一点:

  1. 用bash否定退出状态(没有其他答案这样说):

    if ! [ -e "$file" ]; thenecho "file does not exist"fi

    或:

    ! [ -e "$file" ] && echo "file does not exist"
  2. Negate the test inside the test command [ (that is the way most answers before have presented):

    if [ ! -e "$file" ]; thenecho "file does not exist"fi

    或:

    [ ! -e "$file" ] && echo "file does not exist"
  3. Act on the result of the test being negative (|| instead of &&):

    Only:

    [ -e "$file" ] || echo "file does not exist"

    这看起来很傻(IMO),不要使用它,除非您的代码必须可移植到缺少管道否定运算符(!)的Bourne shell(如Solaris 10或更早版本的/bin/sh):

    if [ -e "$file" ]; then:elseecho "file does not exist"fi

[ -f "$file" ]

[命令对存储在$file中的路径执行stat()(不是lstat())系统调用,如果该系统调用成功并且stat()返回的文件类型为“定期”,则返回真正

因此,如果[ -f "$file" ]返回true,您可以判断该文件确实存在并且是一个常规文件或符号链接,最终解析为一个常规文件(或者至少在stat()时是这样)。

但是,如果它返回虚假(或者如果[ ! -f "$file" ]! [ -f "$file" ]返回true),则有许多不同的可能性:

  • 该文件不存在
  • 该文件存在但不是定期文件(可能是设备、FIFO、目录、套接字…)
  • 该文件存在,但您没有父目录的搜索权限
  • 该文件存在,但访问它的路径太长
  • 该文件是指向常规文件的符号链接,但您没有对符号链接解析所涉及的某些目录的搜索权限。
  • stat()系统调用可能失败的任何其他原因。

简而言之,它应该是:

if [ -f "$file" ]; thenprintf '"%s" is a path to a regular file or symlink to regular file\n' "$file"elif [ -e "$file" ]; thenprintf '"%s" exists but is not a regular file\n' "$file"elif [ -L "$file" ]; thenprintf '"%s" exists, is a symlink but I cannot tell if it eventually resolves to an actual file, regular or not\n' "$file"elseprintf 'I cannot tell if "%s" exists, let alone whether it is a regular file or not\n' "$file"fi

要确定文件不存在,我们需要stat()系统调用返回错误代码ENOENTENOTDIR告诉我们路径组件之一不是目录,这是我们可以通过该路径判断文件不存在的另一种情况)。不幸的是,[命令没有让我们知道这一点。无论错误代码是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; fidoes not exist$ if ! ls -Ld -- "$file" > /dev/null; then echo stat failed; fils: cannot access '/var/spool/cron/crontabs/root': Permission deniedstat failed

至少ls告诉我它失败不是因为文件不存在。这是因为它无法判断文件是否存在。[命令只是忽略了这个问题。

使用zsh shell,您可以在失败的[命令之后使用$ERRNO特殊变量查询错误代码,并使用zsh/system模块中的$errnos特殊数组解码该数字:

zmodload zsh/systemERRNO=0if [ ! -f "$file" ]; thenerr=$ERRNOcase $errnos[err] in("") echo exists, not a regular file;;(ENOENT|ENOTDIR)if [ -L "$file" ]; thenecho broken linkelseecho does not existfi;;(*) syserror -p "can't tell: " "$err"esacfi

(注意当使用#2的最新版本构建时,#1的某些版本破坏了#0支持

有时使用&&和||运算符可能很方便。

例如(如果您有命令“test”):

test -b $FILE && echo File not there!

test -b $FILE || echo File there!

您还可以将多个命令组合在一个班轮中

[ -f "filename" ] || ( echo test1 && echo test2 && echo test3 )

[ -f "filename" ] || { echo test1 && echo test2 && echo test3 ;}

如果文件名不退出,输出将是

test1test2test3

说明:(…)在子shell中运行,{…;}在同一个shell中运行。

如果你想使用test而不是[],那么你可以使用!来获得否定:

if ! test "$FILE"; thenecho "does not exist"fi
envfile=.env
if [ ! -f "$envfile" ]thenecho "$envfile does not exist"exit 1fi