如何判断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 

testing命令( [这里]有一个“不”)逻辑运算符,这是感叹号(类似于许多其他语言)。 尝试这个:

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

Bash文件testing

-b filename – 阻止特殊文件
-c filename – 特殊字符文件
-d directoryname – 检查目录是否存在
-e filename – 检查文件是否存在,无论types(节点,目录,套接字等)
-f filename – 检查常规文件存在不是一个目录
-G filename – 检查文件是否存在,是否被有效的组ID所拥有
-G filename set-group-id – 如果文件存在并且是set-group-id,则为真
-k filename – 粘性位
-L filename – 符号链接
-O filename – 如果文件存在并由有效用户标识拥有,则为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 

testingexpression式可以通过使用! 操作者

 #!/bin/bash file=./file if [ ! -e "$file" ]; then echo "File does not exist" else echo "File exists" fi 

你可以用“!”否定expression式:

 #!/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兼容的格式来完成下面的一行代码:

 $ [ -f "/$DIR/$FILE" ] || echo "$FILE NOT FOUND" $ [ -f "/$DIR/$FILE" ] && echo "$FILE FOUND" 

对于一些命令,就像我在脚本中所做的那样:

 $ [ -f "/$DIR/$FILE" ] || { echo "$FILE NOT FOUND" ; exit 1 ;} 

一旦我开始这样做,我很less再使用完全types的语法!

要testing文件的存在,参数可以是以下任何一个:

 -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 

以下所有testing适用于常规文件,目录和符号链接:

 -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 

您应该小心运行未引用的variables的test ,因为它可能会产生意外的结果:

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

build议通常是将testingvariables包围在双引号内:

 #!/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. 在testing命令内部否定testing[ (这是大多数人在回答之前的答案):

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

    要么:

     [ ! -e "$file" ] && echo "file does not exist" 
  3. 对testing结果采取负面行动(而不是&& ):

    只要:

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

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

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

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

 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 

可以写成(使用“和”运算符:&&):

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

这看起来像这样短:

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

test东西也可以算。 它为我工作(基于Bash Shell:检查文件是否存在 ):

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

这个代码也工作。

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

 [ -f "$file" ] 

[命令对存储在$file的path执行stat() (不是lstat() )系统调用,如果系统调用成功并且stat()返回的文件types为“regular”,则返回true

因此,如果[ -f "$file" ]返回true,那么可以告诉文件确实存在,并且是普通文件或符号链接,最终parsing为常规文件(或者至less在stat() )。

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

  • 该文件不存在
  • 该文件存在,但不是一个普通的文件
  • 该文件存在但您没有对父目录的search权限
  • 该文件存在,但访问它的path太长
  • 该文件是一个常规文件的符号链接,但是您不具有对符号链接parsing中涉及的某些目录的search权限。
  • …为什么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()系统调用返回一个错误代码ENOENTENOTDIR告诉我们其中一个path组件不是一个目录是另一种情况,我们可以告诉该文件不存在该path)。 不幸的是,这个命令并不让我们知道。 无论错误代码是ENOENT,EACCESS(权限被拒绝),ENAMETOOLONG还是别的,它都会返回false。

[ -e "$file" ]testing也可以用ls -Ld -- "$file" > /dev/null 。 在这种情况下, ls会告诉你为什么stat()失败,尽pipe信息不能以编程方式使用:

 $ 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 

至lessls告诉我,这不是因为该文件不存在,它失败了。 这是因为它不能分辨文件是否存在。 [命令刚刚忽略了这个问题。

通过zsh shell,你可以在失败的命令后用$ERRNO特殊variables查询错误代码,并使用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;; (*) echo "can't tell"; syserror "$err" esac fi 

(注意, 当使用最新版本的gcc构build时 , $errnos支持已经被zsh某些版本所破坏 )。

你可以使用特定的Bash:

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

要么

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

如果要检查文件和文件夹,则使用-e选项而不使用-f

最简单的方法

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

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

 echo "enter file" read -ra if [ -s /home/trainee02/"$a" ] then echo "yes. file is there." else echo "sorry. file is not there." fi 

有时使用&&和||可能会很方便 运营商。

像在(如果你有命令“testing”):

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

要么

 test -b $FILE || echo File there!