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

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

#!/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 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 testhelp [用于内置的 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

你可以这样做:

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

要么

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

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

您应该对未带引号的变量进行test ,因为它可能会产生意外的结果:

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

通常建议将测试的变量括在双引号中:

#!/bin/sh
FILE=$1

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

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

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

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

    要么:

    ! [ -e "$file" ] && echo "file does not exist"
  2. 否定测试命令中的测试[ (这是以前大多数答案提出的方式):

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

    要么:

    [ ! -e "$file" ] && echo "file does not exist"
  3. 对测试结果为负( ||代替&& )采取行动:

    只要:

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

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

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