天天看點

如何判斷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?

繼續閱讀