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 vorhanden ist?
#!/bin/bash
FILE=$1
if [ $FILE does not exist ]; then
echo "File $FILE does not exist."
fi
if [ -f $FILE ]; then; else; echo "File $FILE does not exist."; fi;
Wahrscheinlich gut, dass ich diese Frage stattdessen gefunden und gelernt habe, sie besser zu machen. :)-e
. -f nimmt keine Verzeichnisse, Symlinks usw. auf.FILE=$1
->FILE="$1"
undif [ -f $FILE ];
->if [ -f "$FILE" ];
Antworten:
Der Testbefehl (
[
hier) hat einen logischen Operator "nicht", der das Ausrufezeichen ist (ähnlich wie in vielen anderen Sprachen). Versuche dies:quelle
if [ ! \( -f "f1" -a -f "f2" \) ] ; then echo MISSING; fi
if [ ! -f "f1" ] || [ ! -f "f2" ] ; then echo MISSING; fi
[ -f /tmp/foo.txt ] || echo "File not found!"
-e: Returns true value, if file exists
-f: Return true value, if file exists and regular file
-r: Return true value, if file exists and is readable
-w: Return true value, if file exists and is writable
-x: Return true value, if file exists and is executable
-d: Return true value, if exists and is a directory
! -f
mit&&
gegenüber der Verwendung-f
mit||
. Dies hat mit dem Exit-Code zu tun, der von der Nichtexistenzprüfung zurückgegeben wird. Wenn Ihre Leitung immer sauber mit dem Exit-Code 0 beendet werden muss (und diese Einschränkung manchmal nicht gewünscht wird), sind die beiden Ansätze nicht austauschbar. Alternativ können Sie auch einfach eineif
Anweisung verwenden, und Sie müssen sich nicht mehr um den Exit-Code Ihrer Nichtexistenzprüfung kümmern.Testen von Bash-Dateien
-b filename
- Sonderdatei blockieren-c filename
- Sonderzeichendatei-d directoryname
- Auf Verzeichnisexistenz prüfen-e filename
- Auf Dateiexistenz prüfen, unabhängig vom Typ (Knoten, Verzeichnis, Socket usw.)-f filename
- Auf reguläre Dateiexistenz prüfen, kein Verzeichnis-G filename
- Prüfen, ob eine Datei existiert und deren Eigentümer ist effektive Gruppen-ID-G filename set-group-id
- True, wenn die Datei vorhanden ist und die Gruppen-ID festgelegt ist-k filename
- Sticky-Bit-L filename
- Symbolischer Link-O filename
- True, wenn die Datei vorhanden ist 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 Socket ist-s filename
- Überprüfen Sie, ob Datei hat eine Größe ungleich Null-u filename
- Überprüfen Sie, ob das Dateisatz-Benutzer-ID-Bit gesetzt ist.-w filename
- Überprüfen Sie, ob die Datei beschreibbar ist.-x filename
- Überprüfen Sie, ob die Datei ausführbar istWie benutzt man:
Ein Testausdruck kann mit dem
!
Operator negiert werdenquelle
-n String
- Überprüfe, ob die Länge der Zeichenfolge nicht Null ist. Oder meinst dufile1 -nt file2
- Überprüfen Sie, ob Datei1 neuer als Datei 2 ist (Sie können -ot auch für ältere dann verwenden)The unary operator -z tests for a null string, while -n or no operator at all returns True if a string is not empty.
~ ibm.com/developerworks/library/l-bash-test/index.htmlSie können einen Ausdruck mit "!" Negieren:
Die relevante Manpage ist
man test
oder gleichwertigman [
- oderhelp test
oderhelp [
für den eingebauten Befehl bash.quelle
[
ist ein builtin. Die relevanten Informationen werden also eher vonhelp [
... erhalten, aber dies zeigt, dass dies[
ein Synonym für dastest
Eingebaute ist, daher werden die relevanten Informationen eher von erhaltenhelp test
. Siehe auch den Abschnitt Bash Conditional Expression im Handbuch .[
Befehl bash verhält sich sehr ähnlich wie der externe[
Befehl. Entwederman test
oderman [
gibt Ihnen eine gute Vorstellung davon, wie er funktioniert.[
mehr Schalter enthält als der externe Befehl[
auf meinem System ... Im Allgemeinen halte ich es für besser, die Dokumentation zu lesen, die für ein bestimmtes Tool spezifisch ist, und nicht die Dokumentation, die für ein anderes vage verwandtes Tool spezifisch ist. Ich könnte mich jedoch irren;)
Es ist auch möglich, dass die Datei eine fehlerhafte symbolische Verknüpfung oder eine nicht reguläre Datei ist, z. B. ein Socket, ein Gerät oder ein Fifo. So fügen Sie beispielsweise eine Überprüfung auf fehlerhafte Symlinks hinzu:
quelle
Es ist erwähnenswert, dass Sie abkürzen können, wenn Sie einen einzelnen Befehl ausführen müssen
zu
oder
quelle
Ich bevorzuge den folgenden Einzeiler im POSIX- Shell-kompatiblen Format:
Für ein paar Befehle, wie ich es in einem Skript tun würde:
Sobald ich damit angefangen habe, verwende ich selten mehr die vollständig typisierte Syntax !!
quelle
[
oder dastest
eingebaute Element standardmäßig (im Gegensatz zu ) auf das Vorhandensein von Dateien in der Datei testen würde-e
? Wäre das nicht mehrdeutig? AFAIK (und AIUI der Abschnitt "CONDITIONAL EXPRESSIONS") Das einzige, was mit Ihrem Ansatz getestet wird, ist, dass das Argument nicht leer (oder undefiniert) ist, was in diesem Fall eine Tautologie ist (let$DIR = ''
and$FILE = ''
, dann ist das Argument immer noch'//'
).ls /foo
, Ergebnisls: cannot access /foo: No such file or directory
.[ /foo ] && echo 42
Ergebnis42
. GNU Bash, Version 4.2.37 (1) -Veröffentlichung (i486-pc-linux-gnu).-f
Option nicht angegeben, als ich diese Antwort schrieb. Natürlich können Sie immer verwenden-e
, wenn Sie nicht sicher sind, ob es sich um eine reguläre Datei handelt. Zusätzlich zitiere ich in all meinen Skripten diese Konstrukte, ich muss dies nur ohne ausreichenden Beweis eingereicht haben.[ $condition ] && if_true || if_false
ist fehleranfällig. Auf jeden Fall finde ich[ ! -f "$file" ] && if_not_exists
leichter zu lesen und zu verstehen als[ -f "$file" ] || if_not_exists
.Um die Existenz von Dateien zu testen, kann der Parameter einer der folgenden sein:
Alle folgenden Tests gelten für reguläre Dateien, Verzeichnisse und Symlinks:
Beispielskript:
quelle
Du kannst das:
oder
Wenn Sie nach Datei und Ordner suchen möchten, verwenden Sie
-e
stattdessen die Option-f
.-e
Gibt true für reguläre Dateien, Verzeichnisse, Sockets, Zeichenspezialdateien, Blockspezialdateien usw. zurück.quelle
[
.-f
) und Verzeichnisse sind nur zwei von vielen verschiedenen Arten von Dateien . Es gibt auch Sockets, Symlinks, Geräte, Fifos, Türen ...,[ -e
die nach der Symlink-Auflösung die Existenz von Dateien (aller Art, einschließlich regulär, FIFO, Verzeichnis ...) prüfen .-e
, er braucht-f
.Sie sollten vorsichtig sein, wenn Sie
test
für eine nicht zitierte Variable ausgeführt werden, da dies zu unerwarteten Ergebnissen führen kann:Die Empfehlung lautet normalerweise, die getestete Variable in doppelte Anführungszeichen zu setzen:
quelle
[ ... ]
.Es gibt drei verschiedene Möglichkeiten, dies zu tun:
Negieren Sie den Exit-Status mit Bash (keine andere Antwort hat dies gesagt):
Oder:
Negieren Sie den Test innerhalb des Testbefehls
[
(so haben die meisten Antworten zuvor dargestellt):Oder:
Handle auf das Ergebnis des Tests, das negativ ist (
||
anstatt&&
):Nur:
Dies sieht albern aus (IMO). Verwenden Sie es nur, wenn Ihr Code auf die Bourne-Shell (wie die
/bin/sh
von Solaris 10 oder früher) portierbar sein muss, auf der der Pipeline-Negationsoperator (!
) fehlte :quelle
! [
und[ !
?! [
ist POSIX für Shell-Pipelines 2.9.2 (ein beliebiger Befehl)Otherwise, the exit status shall be the logical NOT of the exit status of the last command
und[ !
POSIX für Test! expression True if expression is false. False if expression is true.
. Beide sind also POSIX, und meiner Erfahrung nach werden beide umfassend unterstützt.!
Schlüsselwort, das von der Korn-Shell eingeführt wurde. Außer vielleicht für Solaris 10 und älter ist es heutzutage unwahrscheinlich, dass Sie auf eine Bourne-Shell stoßen.Im
Der
[
Befehl führt einenstat()
(nichtlstat()
) Systemaufruf für den in gespeicherten Pfad aus$file
und gibt true zurück , wenn dieser Systemaufruf erfolgreich ist und der von zurückgegebene Dateitypstat()
" normal " ist.Wenn also
[ -f "$file" ]
true zurückgegeben wird, können Sie feststellen, dass die Datei vorhanden ist und eine reguläre Datei oder ein Symlink ist, der schließlich in eine reguläre Datei aufgelöst wird (oder zumindest zum Zeitpunkt derstat()
).Wenn jedoch false zurückgegeben wird (oder if
[ ! -f "$file" ]
oder! [ -f "$file" ]
true zurückgegeben wird), gibt es viele verschiedene Möglichkeiten:stat()
Systemaufruf fehlschlagen kann.Kurz gesagt sollte es sein:
Um sicher zu sein, dass die Datei nicht existiert, benötigen wir die
stat()
Systemaufruf mit dem FehlercodeENOENT
(gibt anENOTDIR
, dass eine der Pfadkomponenten kein Verzeichnis ist, ein weiterer Fall, in dem wir feststellen können, dass die Datei nicht vorhanden ist) zurückkehren existieren auf diesem Weg). Leider[
lässt uns der Befehl das nicht wissen. Es wird false zurückgegeben, unabhängig davon, ob der Fehlercode ENOENT, EACCESS (Berechtigung verweigert), ENAMETOOLONG oder etwas anderes ist.Der
[ -e "$file" ]
Test kann auch mit durchgeführt werdenls -Ld -- "$file" > /dev/null
. In diesem Fallls
erfahren Sie, warum diesstat()
fehlgeschlagen ist, obwohl die Informationen nicht einfach programmgesteuert verwendet werden können:Zumindest
ls
sagt mir, dass es nicht daran liegt, dass die Datei nicht existiert. Dies liegt daran, dass nicht festgestellt werden kann, ob die Datei vorhanden ist oder nicht. Der[
Befehl hat das Problem einfach ignoriert.Mit der
zsh
Shell können Sie den Fehlercode mit der$ERRNO
speziellen Variablen nach dem fehlgeschlagenen[
Befehl abfragen und diese Nummer mithilfe des$errnos
speziellen Arrays in der dekodierenzsh/system
Modul :(Vorsicht, die
$errnos
Unterstützung wurde bei einigen Versionen von unterbrochen,zsh
wenn sie mit neueren Versionen von erstellt wurden.gcc
)quelle
Verwenden Sie "!", Um einen Test umzukehren. Dies entspricht dem logischen Operator "nicht" in anderen Sprachen. Versuche dies:
Oder etwas anders geschrieben:
Oder Sie könnten verwenden:
Oder alles zusammen drücken:
Was geschrieben werden kann (unter Verwendung des Operators "und": &&) als:
Was so kürzer aussieht:
quelle
Das
test
Ding kann auch zählen. Es hat bei mir funktioniert (basierend auf Bash Shell: Datei vorhanden oder nicht vorhanden ):quelle
Dieser Code funktioniert auch.
quelle
Der einfachste Weg
quelle
Dieses Shell-Skript funktioniert auch zum Suchen einer Datei in einem Verzeichnis:
quelle
read -p "Enter file name: " -r a
zum Auffordern als auch zum Lesen verwendet werden. Es werden Anführungszeichen um die Variable verwendet. das ist gut, sollte aber erklärt werden. Es ist möglicherweise besser, wenn der Dateiname wiedergegeben wird. Und dies prüft, ob die Datei existiert und nicht leer ist (das ist die Bedeutung von-s
), während die Frage nach einer leeren oder nicht leeren Datei fragt (für die dies-f
besser geeignet ist).Manchmal kann es nützlich sein, && und || zu verwenden Betreiber.
Wie in (wenn Sie den Befehl "test" haben):
oder
quelle
Wenn Sie
test
anstelle von verwenden möchten,[]
können Sie Folgendes verwenden!
, um die Negation zu erhalten:quelle
Sie können auch mehrere Befehle in einem Liner gruppieren
[ -f "filename" ] || ( echo test1 && echo test2 && echo test3 )
oder
[ -f "filename" ] || { echo test1 && echo test2 && echo test3 ;}
Wenn der Dateiname nicht beendet wird, wird die Ausgabe ausgeführt
Hinweis: (...) wird in einer Subshell ausgeführt, {...;} wird in derselben Shell ausgeführt.
Die geschweifte Klammer funktioniert nur in Bash.quelle
quelle