bash - wenn - linux shell script datei existiert




Wie erfahre ich, ob in Bash keine reguläre Datei vorhanden ist? (12)

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

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

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 überprüfen möchte, ob die Datei nicht existiert?

#!/bin/bash

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


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

Dieses Shell-Skript funktioniert auch zum Suchen einer Datei in einem Verzeichnis:

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

Es gibt drei verschiedene 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 dargestellt):

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

    Oder:

    [ ! -e "$file" ] && echo "file does not exist"
    
  3. Negieren Sie das Ergebnis des Tests ( || anstelle von && ):

    Nur:

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

    Dies sieht dumm aus (IMO). Verwenden Sie es nicht, es sei denn, Ihr Code muss in die Bourne-Shell portierbar sein (wie /bin/sh von Solaris 10 oder früher), die keinen Pipeline-Negationsoperator ( ! ) Hatte:

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

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

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

zu

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

oder

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

Im

[ -f "$file" ]

Der Befehl [ befiehlt einen stat() (nicht lstat() ) Systemaufruf für den in $file gespeicherten Pfad und gibt true zurück , wenn der Systemaufruf erfolgreich ist und der Typ der Datei, wie von stat() "normal" ist.

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 werden kann (oder zumindest zum Zeitpunkt stat() ).

Wenn jedoch false zurückgegeben wird (oder [ ! -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
  • Die Datei ist vorhanden, 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.
  • ... irgendein 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 sicher zu sein, dass die Datei nicht existiert, benötigen wir den stat() - Systemaufruf, um den Fehlercode ENOENT ( ENOTDIR sagt uns, dass eine der Pfadkomponenten kein Verzeichnis ist. In einem anderen Fall können wir das feststellen.) Die Datei existiert nicht unter diesem Pfad. Leider lässt uns das [ Kommando nicht wissen. Es wird false zurückgegeben, wenn der Fehlercode ENOENT, EACCESS (Berechtigung verweigert), ENAMETOOLONG oder irgendetwas anderes ist.

Der [ -e "$file" ] Test kann auch mit ls -Ld -- "$file" > /dev/null . In diesem Fall sagt Ihnen ls , 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 mir ls , dass es nicht daran liegt, dass die Datei nicht existiert, dass sie fehlschlägt. Es liegt daran, dass es nicht erkennen kann, ob die Datei existiert oder nicht. Der Befehl [ das Problem einfach ignoriert.

Mit der zsh Shell können Sie den Fehlercode mit der $ERRNO nach dem fehlgeschlagenen [ Befehl abfragen und diese Nummer mit dem $errnos Spezialarray 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;;
    (*) echo "can't tell"; syserror "$err"
  esac
fi

(Achtung: Die Unterstützung für $errnos ist bei einigen Versionen von zsh wenn sie mit den letzten Versionen von gcc ).


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!

Sie sollten beim Ausführen eines test für eine nicht notierte Variable 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

Um die Existenz der 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 Tests unten 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

Bash-Datei testen

-b filename - Spezialdatei blockieren
-c filename - Datei mit Sonderzeichen
-d directoryname - Überprüfen Sie, -d directoryname
-e filename - Prüfung auf Vorhandensein von Dateien, unabhängig von Typ (Knoten, Verzeichnis, Socket usw.)
-f filename - Überprüfe, ob reguläre Dateien vorhanden sind, kein Verzeichnis
-G filename - Prüfen Sie, ob die Datei existiert und der effektiven Gruppen-ID gehört
-G filename set-group-id - True, wenn die Datei existiert und die Set-Group-ID ist
-k filename - Klebriges Bit
-L filename - symbolischer Link
-O filename - True, wenn die Datei existiert und der effektiven Benutzer-ID gehört
-r filename - Prüfen Sie, ob die Datei lesbar ist
-S filename - Prüfen Sie, ob die Datei Socket ist
-s filename - Prüfen Sie, ob die Datei eine andere Größe als Null hat
-u filename - Prüfen Sie, ob das Set-User-ID-Bit der Datei gesetzt ist
-w filename - Prüfen Sie, ob die Datei beschreibbar ist
-x filename - Prü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 ! Negiert werden ! Operator

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

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

Es ist auch möglich, dass es sich bei der Datei um einen defekten symbolischen Link oder um eine nicht reguläre Datei handelt, wie z. B. ein Socket, ein Gerät oder ein FIFO. So fügen Sie beispielsweise eine Überprüfung auf beschädigte 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




scripting