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
Der test
kann auch zählen. Es hat für mich funktioniert (basierend auf Bash Shell: Vorhandene Dateien prüfen oder nicht ):
test -e FILENAME && echo "File exists" || echo "File doesn't exist"
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:
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"
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"
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