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

如何判断Bash中是否不存在常规文件?,bash,file-io,scripting,Bash,File Io,Scripting,我使用以下脚本查看文件是否存在: #!/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

我使用以下脚本查看文件是否存在:

#!/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
命令(
[
此处)有一个“not”逻辑运算符,它是感叹号(类似于许多其他语言)。请尝试以下操作:

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

可以用“!”来否定表达式:

对于内置bash命令,相关的手册页是
man test
,或者相当于
man[
——或者
help test
或者
help[

[[ -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
-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

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

if [ ! -f "$file" ]; then
    echo "$file"
fi


我更喜欢以与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/sh
FILE=$1

if [ ! -f "$FILE" ]
then
   echo "File $FILE does not exist."
fi

测试
这件事可能也很重要。它对我很有用(基于):

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

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
或者,一起预测:

if ! [ -f /tmp/foo.txt ]; then echo "File not found!"; fi
可将其写入(使用then“and”运算符:&&&)为:

它看起来像这样短:

[ -f /tmp/foo.txt ] || echo "File not found!"

此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

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

-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
以下所有测试均适用于常规文件、目录和符号链接:

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
-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

Bash文件测试

-b文件名
-阻止特殊文件
-c文件名
-特殊字符文件
-d directoryname
-检查目录是否存在
-e filename
-检查文件是否存在,而不考虑类型(节点、目录、套接字等)
-f filename
-检查常规文件是否存在而不是目录
-G filename
-检查文件是否存在并且是否由有效的组ID拥有
-G filename set group id
-如果文件存在并且设置了组id,则为True
-k文件名
-Sticky位
-L文件名
-符号链接
-O filename
-如果文件存在且由有效用户id拥有,则为True
-r文件名
-检查文件是否可读
-S文件名
-检查文件是否为套接字
-s文件名
-检查文件大小是否为非零
-u filename
-检查是否设置了文件集用户id位
-w文件名
-检查文件是否可写
-x文件名
-检查文件是否可执行

如何使用:

#!/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 
最简单的方法

FILE=$1
[ ! -e "${FILE}" ] && echo "does not exist" || echo "exists"
您可以这样做:

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


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

此代码也有效

#!/bin/bash
FILE=$1
if [ -f $FILE ]; then
 echo "File '$FILE' Exists"
else
 echo "The File '$FILE' Does Not Exist"
fi

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

  • 用bash否定退出状态(没有其他答案这么说):

    或:

  • 在test命令
    [
    中否定测试(这是以前大多数答案的表达方式):

    或:

  • 在测试结果为阴性时采取行动(
    |
    而不是
    &&
    ):

    仅:

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

  • [
    命令对存储在
    $file
    中的路径执行
    stat()
    (而不是
    lstat()
    )系统调用,如果系统调用成功且
    stat()
    返回的文件类型为“常规”,则返回true

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

    但是,如果返回false(或如果
    [!-f“$file”]
    ![-f“$file”]
    返回true),则有许多不同的可能性:

    • 该文件不存在
    • 该文件存在,但不是常规文件(可能是设备、fifo、目录、套接字…)
    • 文件存在,但您没有父目录的搜索权限
    • 文件存在,但访问该文件的路径太长
    • 该文件是常规文件的符号链接,但您没有对符号链接解析中涉及的某些目录的搜索权限
    • …系统调用可能失败的任何其他原因
    简言之,应该是:

    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()
    系统调用返回一个错误代码
    enoint
    ENOTDIR
    告诉我们其中一个路径组件不是目录,在另一种情况下,我们可以通过该路径判断文件不存在)。不幸的是
    [
    命令不让我们知道这一点。无论错误代码是enoint、EACCESS(权限被拒绝)、enametolong还是其他任何代码,它都将返回false

    [-e“$file”]
    测试也可以使用
    ls-Ld--“$file”>/dev/null
    完成。在这种情况下,
    ls
    将告诉您原因
    #!/bin/bash
    FILE=$1
    if [ -f $FILE ]; then
     echo "File '$FILE' Exists"
    else
     echo "The File '$FILE' Does Not Exist"
    fi
    
    if ! [ -e "$file" ]; then
        echo "file does not exist"
    fi
    
    ! [ -e "$file" ] && echo "file does not exist"
    
    if [ ! -e "$file" ]; then
        echo "file does not exist"
    fi
    
    [ ! -e "$file" ] && echo "file does not exist"
    
    [ -e "$file" ] || echo "file does not exist"
    
    if [ -e "$file" ]; then
        :
    else
        echo "file does not exist"
    fi
    
    [ -f "$file" ]
    
    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
    
    $ 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
    
    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
    
    test -b $FILE && echo File not there!
    
    test -b $FILE || echo File there!
    
    test1
    test2
    test3
    
    if ! test "$FILE"; then
      echo "does not exist"
    fi
    
    envfile=.env
    
    if [ ! -f "$envfile" ]
    then
        echo "$envfile does not exist"
        exit 1
    fi