Jak sprawdzić, czy zwykły plik nie istnieje w Bash?

Użyłem następującego skryptu, aby sprawdzić, czy plik istnieje:

#!/bin/bash

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

Jaka jest poprawna składnia, jeśli chcę tylko sprawdzić, czy plik nie istnieje?

#!/bin/bash

FILE=$1     
if [ $FILE does not exist ]; then
   echo "File $FILE does not exist."
fi
Author: codeforester, 2009-03-12

17 answers

Polecenie test ([ tutaj) ma operator logiczny" Nie", który jest wykrzyknikiem (podobnie jak wiele innych języków). Spróbuj tego:

if [ ! -f /tmp/foo.txt ]; then
    echo "File not found!"
fi
 3656
Author: John Feminella,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-13 14:55:36

Testowanie Plików Bash

-b filename - Blokuj plik specjalny
-c filename - Plik znaków specjalnych
-d directoryname - Sprawdź istnienie katalogu
-e filename - Sprawdź istnienie pliku, niezależnie od typu (węzeł, katalog, Gniazdo, itp.)
-f filename - sprawdź, czy zwykły plik nie jest katalogiem
-G filename - Sprawdź, czy plik istnieje i jest własnością efektywnego ID grupy
-G filename set-group-id - True Jeśli plik istnieje i ma identyfikator set-group-id
-k filename - Sticky bit
-L filename - dowiązanie symboliczne
-O filename - True Jeśli plik istnieje i jest własnością efektywnego id użytkownika
-r filename - sprawdź, czy plik jest czytelny
-S filename - sprawdź czy plik jest gniazdem
-s filename - sprawdź, czy plik jest niezerowy
-u filename - sprawdź, czy bit set-user-id jest ustawiony
-w filename - sprawdź, czy plik jest zapisywalny
-x filename - sprawdź czy plik jest wykonywalny

Jak używać:

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

A wyrażenie testowe można negować za pomocą operatora !

#!/bin/bash
file=./file
if [ ! -e "$file" ]; then
    echo "File does not exist"
else 
    echo "File exists"
fi 
 456
Author: BlueCacti,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-08 16:02:43

Możesz negować wyrażenie przez "!":

#!/bin/bash
FILE=$1

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

Odpowiednią stroną podręcznika jest man test lub, równoważnie, man [ -- lub help test lub help [ dla wbudowanego polecenia bash.

 254
Author: starbeamrainbowlabs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-07 10:43:13
[[ -f $FILE ]] || printf '%s does not exist!\n' "$FILE"

Możliwe jest również, że plik jest zepsutym dowiązaniem symbolicznym lub plikiem niestandardowym, takim jak np. Gniazdo, urządzenie lub fifo. Na przykład, aby dodać sprawdzenie pod kątem uszkodzonych dowiązań symbolicznych:

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
 111
Author: guns,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-14 01:41:08

Warto wspomnieć, że jeśli trzeba wykonać jedną komendę można skrócić

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

Do

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

Lub

[ -f "$file" ] || echo "$file"
 81
Author: Elazar Leibovich,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-14 01:44:56

Wolę wykonać następujące jednolinijkowe, w POSIX formacie zgodnym z powłoką:

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

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

Za kilka komend, tak jak ja bym zrobił w skrypcie:

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

Kiedy zacząłem to robić, rzadko używam już w pełni wpisanej składni!!

 57
Author: J. M. Becker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-15 07:34:56

Aby sprawdzić istnienie pliku, parametr może być dowolny z następujących:

-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

Wszystkie poniższe testy dotyczą zwykłych plików, katalogów i dowiązań symbolicznych:

-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

Przykładowy skrypt:

#!/bin/bash
FILE=$1

if [ -f "$FILE" ]; then
   echo "File $FILE exists"
else
   echo "File $FILE does not exist"
fi
 37
Author: SD.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-11 04:32:00

Należy uważać na uruchamianie test dla zmiennej nienotowanej, ponieważ może ona przynieść nieoczekiwane rezultaty:

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

Zaleca się, aby badana zmienna otoczona była podwójnymi cudzysłowami:

#!/bin/sh
FILE=$1

if [ ! -f "$FILE" ]
then
   echo "File $FILE does not exist."
fi
 28
Author: artdanil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-15 07:35:31

Istnieją trzy różne sposoby, aby to zrobić:

  1. Neguj status wyjścia za pomocą bash (żadna inna odpowiedź nie powiedziała tego):

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

    Lub:

    ! [ -e "$file" ] && echo "file does not exist"
    
  2. Odrzuć test wewnątrz polecenia test [ (tak prezentowało się większość odpowiedzi wcześniej):

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

    Lub:

    [ ! -e "$file" ] && echo "file does not exist"
    
  3. Działanie na wynik testu negatywny (|| zamiast &&):

    Tylko:

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

    To wygląda głupio (IMO), Nie używaj go, chyba że Twój kod musi być przenośny do powłoki Bourne ' a (jak /bin/sh z Solarisa 10 lub wcześniejszego), która nie ma operatora negacji potoków(!):

    if [ -e "$file" ]; then
        :
    else
        echo "file does not exist"
    fi
    
 18
Author: Stephane Chazelas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-14 21:20:16

Możesz to zrobić:

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

Lub

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

Jeśli chcesz sprawdzić zarówno Plik, jak i folder, użyj opcji -e zamiast -f. -e zwraca true dla zwykłych plików, katalogów, gniazd, specjalnych plików znakowych, blokowych plików specjalnych itp.

 18
Author: Jahid,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-09 18:59:18

W

[ -f "$file" ]

Polecenie [ wykonuje stat() (Nie lstat()) wywołanie systemowe na ścieżce przechowywanej w $file i zwraca true jeśli wywołanie systemowe powiedzie się, A Typ pliku zwracany przez stat() jest "regularny".

Więc jeśli [ -f "$file" ] zwróci true, możesz powiedzieć, że plik istnieje i jest zwykłym plikiem lub dowiązaniem symbolicznym, które ostatecznie zostanie rozdzielone na zwykły plik(a przynajmniej było to w czasie stat()).

Jeśli jednak zwróci false (lub jeśli [ ! -f "$file" ] lub ! [ -f "$file" ] return true), istnieje wiele różnych możliwości:

  • plik nie istnieje
  • plik istnieje, ale nie jest zwykłym plikiem
  • plik istnieje, ale nie masz uprawnień do wyszukiwania w katalogu nadrzędnym
  • plik istnieje, ale ścieżka dostępu do niego jest zbyt długa
  • plik jest dowiązaniem symbolicznym do zwykłego pliku, ale nie masz uprawnień do przeszukiwania niektórych katalogów zaangażowanych w rozdzielczość dowiązania symbolicznego.
  • ... dowolne inny powód, dla którego wywołanie systemowe stat() może się nie udać.

W skrócie powinno być:

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

Aby mieć pewność, że plik nie istnieje, potrzebujemy wywołania systemowego stat(), aby powrócić z kodem błęduENOENT (ENOTDIR mówi nam, że jeden ze składników path nie jest katalogiem, to kolejny przypadek, w którym możemy stwierdzić, że plik nie istnieje przez tę ścieżkę). Niestety polecenie [ nie daje nam o tym znać. Zwróci false, czy kod błędu jest ENOENT, EACCESS( uprawnienie odmowa), ENAMETOOLONG lub cokolwiek innego.

Test [ -e "$file" ] można również wykonać za pomocą ls -Ld -- "$file" > /dev/null. W takim przypadku ls powie Ci, dlaczego stat() nie powiodło się, choć informacje nie mogą być łatwo użyte programowo:

$ 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

Przynajmniej ls mówi mi, że to nie dlatego, że plik nie istnieje, że zawodzi. To dlatego, że nie może stwierdzić, czy plik istnieje, czy nie. Polecenie [ zignorowało problem.

Za pomocą powłoki zsh można odpytywać kod błędu za pomocą $ERRNO specjalna zmienna po nieudanym poleceniu [ i dekodowanie tej liczby za pomocą specjalnej tablicy $errnos w module zsh/system:

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 wsparcie jest przerwane w niektórych wersjach zsh, gdy zbudowany z ostatnich wersji gcc).

 15
Author: Stephane Chazelas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-20 14:09:58

Aby odwrócić test, użyj "!". Jest to odpowiednik operatora logicznego "not" w innych językach. Spróbuj tego:

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

Lub napisane w nieco inny sposób:

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

Lub możesz użyć:

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

, które można zapisać (używając wtedy operatora" i":&&) jako:

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

Który wygląda krócej Tak:

[ -f /tmp/foo.txt ] || echo "File not found!"
 7
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-04 22:29:20

Rzecz test też może się liczyć. U mnie zadziałało (na podstawie powłoka Bash: sprawdź, czy plik istnieje lub nie):

test -e FILENAME && echo "File exists" || echo "File doesn't exist"
 7
Author: android developer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-26 17:30:05

Ten kod również działa .

#!/bin/bash
FILE=$1
if [ -f $FILE ]; then
 echo "File '$FILE' Exists"
else
 echo "The File '$FILE' Does Not Exist"
fi
 7
Author: Lemon Kazi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-03 08:39:37

Najprostszy sposób

FILE=$1
[ ! -e "${FILE}" ] && echo "does not exist" || echo "exists"
 5
Author: lancerex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-01 01:35:00

Ten skrypt powłoki działa również do znalezienia pliku w katalogu:

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
 3
Author: Simmant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-05 21:01:40

Czasami przydatne może być użycie operatorów && i||.

Jak w (Jeśli masz komendę "test"):

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

Lub

test -b $FILE || echo File there!
 1
Author: André,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-11 20:25:18