天天看点

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

英文原文地址为: How do I tell if a regular file does not exist in Bash?

I've used the following script to see if a file exists:

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

#!/bin/bash

FILE=$1     
if [ -f $FILE ]; then
   echo "File $FILE exists."
else
   echo "File $FILE does not exist."
fi
           

What's the correct syntax to use if I only want to check if the file does not exist?

如果我只想检查文件是否不存在,正确的语法是什么?

#!/bin/bash

FILE=$1     
if [ $FILE does not exist ]; then
   echo "File $FILE does not exist."
fi
           

17 个解决方案

#1

3363  

The test command (

[

here) has a "not" logical operator which is the exclamation point (similar to many other languages). Try this:

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

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

#2

378  

Bash File Testing

Bash文件测试

-b filename

- Block special file

-c filename

- Special character file

-d directoryname

- Check for directory Existence

-e filename

- Check for file existence, regardless of type (node, directory, socket, etc.)

-f filename

- Check for regular file existence not a directory

-G filename

- Check if file exists and is owned by effective group ID

-G filename set-group-id

- True if file exists and is set-group-id

-k filename

- Sticky bit

-L filename

- Symbolic link

-O filename

- True if file exists and is owned by the effective user id

-r filename

- Check if file is a readable

-S filename

- Check if file is socket

-s filename

- Check if file is nonzero size

-u filename

- Check if file set-user-id bit is set

-w filename

- Check if file is writable

-x filename

- Check if file is executable

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -等)- f文件名——检查常规文件的存在不是一个目录- g文件名,检查文件是否存在,是否拥有有效的组ID - g文件名set-group-id——如果文件存在,set-group-id - k文件名——粘贴位- l文件名——符号链接- o文件,如果文件存在,属于有效用户ID - r文件名-检查文件是否可读- s文件名检查文件是否插座- s文件名-检查文件是否非零大小- u文件名检查文件是否set-user-id设置-w文件名-检查文件是否可写-x文件名-检查文件是否可执行?

How to use:

如何使用:

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

A test expression can be negated by using the

!

operator

一个测试表达式可以通过使用!操作符

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

#3

245  

You can negate an expression with "!":

你可以用“!”来否定一个表达式。

#!/bin/bash
FILE=$1

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

The relevant man page is

man test

or, equivalently,

man [

-- or

help test

or

help [

for the built-in bash command.

相关的man页面是man测试,或者,等价地,man[——或者帮助测试或帮助(用于内置bash命令)。

#4

107  

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

Also, it's possible that the file is a broken symbolic link, or a non-regular file, like e.g. a socket, device or fifo. For example, to add a check for broken symlinks:

另外,文件可能是一个损坏的符号链接,或者是一个非规则文件,比如一个插座、设备或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
           

#5

79  

It's worth mentioning that if you need to execute a single command you can abbreviate

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

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

to

test -f "$file" || echo "$file"
           

or

[ -f "$file" ] || echo "$file"
           

#6

54  

I prefer to do the following one-liner, in POSIX shell compatible format:

我更喜欢用POSIX shell兼容格式做以下一行:

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

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

For a couple of commands, like I would do in a script:

对于一些命令,如我在脚本中所做的:

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

Once I started doing this, I rarely use the fully typed syntax anymore!!

一旦我开始这样做,我就很少使用完全类型化的语法了!!

#7

35  

To test file existence, the parameter can be any one of the following:

为了测试文件的存在,参数可以是以下任何一个:

-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
           

All the tests below apply to regular files, directories, and symlinks:

下面的所有测试都适用于常规文件、目录和符号链接:

-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
           

Example script:

示例脚本:

#!/bin/bash
FILE=$1

if [ -f "$FILE" ]; then
   echo "File $FILE exists"
else
   echo "File $FILE does not exist"
fi
           

#8

28  

You should be careful about running

test

for an unquoted variable, because it might produce unexpected results:

对于未引用的变量,您应该注意运行测试,因为它可能会产生意想不到的结果:

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

The recommendation is usually to have the tested variable surrounded by double quotation marks:

建议通常使用双引号包围的测试变量:

#!/bin/sh
FILE=$1

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

#9

17  

There are three distinct ways to do this:

有三种不同的方法:

  1. Negate the exit status with bash (no other answer has said this):

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

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

    Or:

    或者:

    ! [ -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" ]; then
        echo "file does not exist"
    fi
               

    Or:

    或者:

    [ ! -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"
               
    This looks silly (IMO), don't use it unless your code has to be portable to the Bourne shell (like the

    /bin/sh

    of Solaris 10 or earlier) that lacked the pipeline negation operator (

    !

    ):

    这看起来很傻(IMO),除非您的代码必须能够移植到Bourne shell(比如Solaris 10或更早的版本的/bin/sh),否则就不要使用它,因为它缺少管道的否定操作符(!)

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

#10

11  

In

[ -f "$file" ]
           

the

[

command does a

stat()

(not

lstat()

) system call on the path stored in

$file

and returns true if that system call succeeds and the type of the file as returned by

stat()

is "regular".

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

So if

[ -f "$file" ]

returns true, you can tell the file does exist and is a regular file or a symlink eventually resolving to a regular file (or at least it was at the time of the

stat()

).

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

However if it returns false (or if

[ ! -f "$file" ]

or

! [ -f "$file" ]

return true), there are many different possibilities:

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

  • the file doesn't exist
  • 该文件不存在
  • the file exists but is not a regular file
  • 文件存在,但不是常规文件。
  • the file exists but you don't have search permission to the parent directory
  • 文件存在,但您没有搜索权限到父目录。
  • the file exists but that path to access it is too long
  • 文件存在,但是访问它的路径太长。
  • the file is a symlink to a regular file, but you don't have search permission to some of the directories involved in the resolution of the symlink.
  • 这个文件是一个普通文件的符号链接,但是你没有搜索权限到一些涉及到符号链接解析的目录。
  • ... any other reason why the

    stat()

    system call may fail.
  • …stat()系统调用可能失败的其他原因。

In short, it should be:

简而言之,它应该是:

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
           

To know for sure that the file doesn't exist, we'd need the

stat()

system call to return with an error code of

ENOENT

(

ENOTDIR

tells us one of the path components is not a directory is another case where we can tell the file doesn't exist by that path). Unfortunately the

[

command doesn't let us know that. It will return false whether the error code is ENOENT, EACCESS (permission denied), ENAMETOOLONG or anything else.

要确定该文件不存在,我们需要stat()系统调用返回带有ENOENT的错误代码(ENOTDIR告诉我们其中一个路径组件不是目录,这是另一个我们可以告诉文件不存在该路径的情况)。不幸的是,[命令不让我们知道]。如果错误代码是ENOENT、EACCESS(权限被拒绝)、ENAMETOOLONG或其他任何东西,它将返回false。

The

[ -e "$file" ]

test can also be done with

ls -Ld -- "$file" > /dev/null

. In that case,

ls

will tell you why the

stat()

failed, though the information can't easily be used programmatically:

也可以用ls -Ld—“$file”> /dev/null来测试[-e“$file”]测试。在这种情况下,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
           

At least

ls

tells me it's not because the file doesn't exist that it fails. It's because it can't tell whether the file exists or not. The

[

command just ignored the problem.

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

With the

zsh

shell, you can query the error code with the

$ERRNO

special variable after the failing

[

command, and decode that number using the

$errnos

special array in the

zsh/system

module:

使用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;;
    (*) echo "can't tell"; syserror "$err"
  esac
fi
           

(beware the

$errnos

support is broken with some versions of

zsh

when built with recent versions of

gcc

).

(请注意,在使用最新版本的gcc时,$errnos支持会被某些版本的zsh破坏)。

#11

10  

You can use Bash specific:

您可以使用Bash特定:

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

or

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

If you want to check for file and folder both, then use

-e

option instead of

-f

.

如果您想要检查文件和文件夹,那么使用-e选项而不是-f。

#12

7  

To reverse a test, use "!". That is equivalent to the "not" logical operator in other languages. Try this:

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

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

Or written in a slightly different way:

或者以一种稍微不同的方式写:

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

Or you could use:

或者你可以使用:

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

Or, presing all together:

或者,总统在一起:

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

Which may be written (using then "and" operator: &&) as:

可以写(然后用“和”操作符:&&)作为:

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

Which looks shorter like this:

它看起来更短:

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

#13

7  

The

test

thing may count too. It worked for me (based on Bash Shell: Check File Exists or Not):

测试的结果也有可能。它为我工作(基于Bash Shell:检查文件是否存在):

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

#14

7  

This code also working .

这段代码也可以工作。

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

#15

4  

The simplest way

最简单的方法

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

#16

2  

This shell script also works for finding a file in a directory:

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

#17

1  

sometimes it may be handy to use && and || operators.

有时使用&&和||操作符可能很方便。

Like in (if you have command "test"):

像in(如果你有命令“测试”):

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

or

test -b $FILE || echo File there!
           

转载请注明本文地址: How do I tell if a regular file does not exist in Bash?

继续阅读