it-swarm.com.de

Wie kann ich feststellen, ob in Bash keine reguläre Datei vorhanden ist?

Ich habe das folgende Skript verwendet, um festzustellen, ob eine Datei vorhanden ist:

#!/bin/bash

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

Was ist die richtige Syntax, wenn ich nur prüfen möchte, ob die Datei existiert nicht?

#!/bin/bash

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

Der test Befehl ([ hier) hat einen "nicht" logischen Operator, der das Ausrufezeichen ist (ähnlich wie in vielen anderen Sprachen). Versuche dies:

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

Bash File Testing

-b filename - Spezielle Datei blockieren
-c filename - Sonderzeichendatei
-d directoryname - Auf Verzeichnisexistenz prüfen
-e filename - Auf Vorhandensein von Dateien prüfen, unabhängig vom Typ (Knoten, Verzeichnis, Socket usw.)
-f filename - Überprüfen Sie, ob eine reguläre Datei existiert, kein Verzeichnis
-G filename - Überprüfen Sie, ob die Datei vorhanden ist und der gültigen Gruppen-ID gehört
-G filename set-group-id - True, wenn die Datei existiert und die Gruppen-ID gesetzt ist
-k filename - Etwas klebrig
-L filename - Symbolischer Link
-O filename - True, wenn die Datei existiert und der effektiven Benutzer-ID gehört
-r filename - Überprüfen Sie, ob die Datei lesbar ist
-S filename - Überprüfen Sie, ob die Datei ein Socket ist
-s filename - Überprüfen Sie, ob die Datei eine Größe ungleich Null hat
-u filename - Überprüfen Sie, ob das Bit "Datei Set-User-ID" gesetzt ist
-w filename - Überprüfen Sie, ob die Datei beschreibbar ist
-x filename - Überprüfen Sie, ob die Datei ausführbar ist

Wie benutzt man:

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

Ein Testausdruck kann mit dem ! -Operator negiert werden

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

Sie können einen Ausdruck mit "!" Negieren:

#!/bin/bash
FILE=$1

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

Die relevante Manpage ist man test oder entsprechend man [ - oder help test oder help [ für den eingebauten Bash-Befehl.

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

Es ist auch möglich, dass die Datei eine unterbrochene symbolische Verknüpfung oder eine nicht reguläre Datei ist, wie z. eine buchse, ein gerät oder ein fifo. So fügen Sie beispielsweise eine Überprüfung auf fehlerhafte Symlinks hinzu:

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
128
guns

Erwähnenswert ist, dass Sie einen einzelnen Befehl abkürzen können, wenn Sie ihn ausführen müssen

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

zu

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

oder

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

Ich bevorzuge den folgenden Einzeiler im POSIX Shell-kompatiblen Format:

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

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

Für ein paar Befehle, wie ich es in einem Skript tun würde:

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

Sobald ich damit angefangen habe, verwende ich selten mehr die vollständig typisierte Syntax !!

64
J. M. Becker

Um die Existenz einer Datei zu testen, kann der Parameter einer der folgenden sein:

-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

Alle folgenden Tests gelten für reguläre Dateien, Verzeichnisse und 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

Beispielskript:

#!/bin/bash
FILE=$1

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

Du kannst das:

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

oder

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

Wenn Sie nach Dateien und Ordnern suchen möchten, verwenden Sie die Option -e anstelle von -f. -e liefert true für reguläre Dateien, Verzeichnisse, Sockets, Character Special Files, Block Special Files etc.

34
Jahid

Sie sollten beim Ausführen von test für eine Variable ohne Anführungszeichen vorsichtig sein, da dies zu unerwarteten Ergebnissen führen kann:

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

In der Regel wird empfohlen, die getestete Variable in doppelte Anführungszeichen zu setzen:

#!/bin/sh
FILE=$1

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

Es gibt drei Möglichkeiten, dies zu tun:

  1. Negiere den Exit-Status mit bash (keine andere Antwort hat dies gesagt):

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

    Oder:

    ! [ -e "$file" ] && echo "file does not exist"
    
  2. Negieren Sie den Test innerhalb des Testbefehls [ (so haben die meisten Antworten zuvor präsentiert):

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

    Oder:

    [ ! -e "$file" ] && echo "file does not exist"
    
  3. Handeln Sie, wenn das Testergebnis negativ ist (|| anstelle von &&):

    Nur:

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

    Dies sieht albern aus (IMO). Verwenden Sie es nur, wenn Ihr Code auf die Bourne-Shell portierbar sein muss (wie der /bin/sh von Solaris 10 oder früher), dem der Pipeline-Negierungsoperator (!) fehlte. :

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

Im

[ -f "$file" ]

der Befehl [ führt einen Systemaufruf stat() (nicht lstat()) auf dem in $file gespeicherten Pfad aus und gibt true zurück, wenn dieser Systemaufruf erfolgreich ist und der Typ von Die von stat() zurückgegebene Datei ist " regular ".

Wenn also [ -f "$file" ] true zurückgibt, können Sie feststellen, dass die Datei existiert und eine reguläre Datei oder ein Symlink ist, der schließlich in eine reguläre Datei aufgelöst wird (oder zumindest zum Zeitpunkt der stat()).

Wenn es jedoch false zurückgibt (oder wenn [ ! -f "$file" ] oder ! [ -f "$file" ] true zurückgibt), gibt es viele verschiedene Möglichkeiten:

  • die Datei existiert nicht
  • die Datei existiert, ist aber keine reguläre Datei (kann ein Gerät, ein FIFO, ein Verzeichnis, ein Socket sein ...)
  • die Datei existiert, aber Sie haben keine Suchberechtigung für das übergeordnete Verzeichnis
  • die Datei existiert, aber der Zugriffspfad ist zu lang
  • die Datei ist ein Symlink zu einer regulären Datei, aber Sie haben keine Suchberechtigung für einige der Verzeichnisse, die an der Auflösung des Symlinks beteiligt sind.
  • ... ein anderer Grund, warum der Systemaufruf stat() fehlschlagen kann.

Kurz gesagt sollte es sein:

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

Um sicherzugehen, dass die Datei nicht existiert, benötigen wir den Systemaufruf stat(), um den Fehlercode ENOENT zurückzugeben (ENOTDIR gibt an, dass sich eine der Pfadkomponenten befindet kein Verzeichnis ist ein anderer Fall, in dem wir feststellen können, dass die Datei über diesen Pfad nicht existiert). Leider lässt uns der Befehl [ das nicht wissen. Es wird false zurückgegeben, ob der Fehlercode ENOENT, EACCESS (Berechtigung verweigert), ENAMETOOLONG oder etwas anderes ist.

Der [ -e "$file" ]-Test kann auch mit ls -Ld -- "$file" > /dev/null durchgeführt werden. In diesem Fall gibt ls an, warum stat() fehlgeschlagen ist, obwohl die Informationen nicht einfach programmgesteuert verwendet werden können:

$ 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

Zumindest sagt ls, dass es nicht daran liegt, dass die Datei nicht existiert, dass sie fehlschlägt. Dies liegt daran, dass nicht festgestellt werden kann, ob die Datei vorhanden ist oder nicht. Der Befehl [ hat das Problem einfach ignoriert.

Mit der Shell zsh können Sie den Fehlercode mit der Sondervariablen $ERRNO nach dem fehlgeschlagenen Befehl [ abfragen und diese Zahl mit dem Sonderarray $errnos im Modul zsh/system dekodieren:

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

(Beachten Sie, dass die $errnos-Unterstützung bei einigen Versionen von zsh unterbrochen war, als sie mit neueren Versionen von gcc erstellt wurden ).

20

Verwenden Sie "!", Um einen Test umzukehren. Dies entspricht dem logischen Operator "nicht" in anderen Sprachen. Versuche dies:

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

Oder anders geschrieben:

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

Oder Sie könnten verwenden:

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

Oder alles zusammen:

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

Was kann geschrieben werden (mit dann "und" Operator: &&) als:

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

Was so kürzer aussieht:

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

Dieser Code funktioniert auch.

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

Das test Ding kann auch zählen. Es hat bei mir funktioniert (basierend auf Bash Shell: Check File Exists or Not):

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

Der einfachste Weg

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

Dieses Shell-Skript kann auch zum Suchen einer Datei in einem Verzeichnis verwendet werden:

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
5
Simmant

manchmal kann es nützlich sein, && und || zu verwenden Betreiber.

Wie in (wenn Sie den Befehl "test" haben):

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

oder

test -b $FILE || echo File there!
3
André

Wenn Sie test anstelle von [] verwenden möchten, können Sie ! verwenden, um die Negation zu erhalten:

if ! test "$FILE"; then
  echo "does not exist"
fi
0
Mauro Zallocco

Sie können auch mehrere Befehle in einer Zeile gruppieren

[ -f "filename" ] || ( echo test1 && echo test2 && echo test3 )

oder

[ -f "filename" ] || { echo test1 && echo test2 && echo test3 ;}

Wenn Dateiname nicht beendet wird, erfolgt die Ausgabe

test1
test2
test3

Hinweis: (...) wird in einer Subshell ausgeführt, {...;} wird in derselben Shell ausgeführt. Die geschweifte Klammer funktioniert nur in Bash.

0
upteryx