So überprüfen Sie, ob eine Datei in einem Shell-Skript vorhanden ist

175

Ich möchte ein Shell-Skript schreiben, das prüft, ob eine bestimmte Datei archived_sensor_data.jsonvorhanden ist, und sie in diesem Fall löscht. Nach http://www.cyberciti.biz/tips/find-out-if-file-exists-with-conditional-expressions.html habe ich Folgendes versucht:

[-e archived_sensor_data.json] && rm archived_sensor_data.json

Dies löst jedoch einen Fehler aus

[-e: command not found

wenn ich versuche, das resultierende test_controllerSkript mit dem ./test_controllerBefehl auszuführen . Was ist los mit dem Code?

Kurt Peek
quelle
2
Sie müssen ein oder mehrere Leerzeichen zwischen der öffnenden eckigen Klammer "[" und der Option "-e" wie zwischen dem Dateinamen und der schließenden eckigen Klammer "]" setzen
Konstantin Yaniv

Antworten:

349

Es fehlt ein erforderlicher Abstand zwischen der Klammer und -e:

#!/bin/bash
if [ -e x.txt ]
then
    echo "ok"
else
    echo "nok"
fi
chris01
quelle
12
Ich habe schließlich zwei Leerzeichen hinzugefügt, eines nach der öffnenden eckigen Klammer und eines vor dem schließenden : [ -e archived_sensor_data.json ] && rm archived_sensor_data.json. Das Skript scheint jetzt zu funktionieren.
Kurt Peek
3
Dies funktioniert auch mit if [ -e "$1" ](Dateinamen-Eingabeargument).
Edward
2
Der Hauptunterschied besteht darin, dass Sie "Bash" -Skripte anstelle von "Shell" -Skripten verwenden. Beachten Sie, dass die erste Zeile, die Sie hinzugefügt haben, #! / Bin / bash war. Sie weisen den Computer also an, "bash" anstelle von sh zu verwenden. Weil sie dieses Argument "-e" nicht erkennt
Nick Cuevas
29

Hier ist eine alternative Methode mit ls:

(ls x.txt && echo yes) || echo no

Wenn Sie eine Ausgabe ausblenden möchten, lssodass nur Ja oder Nein angezeigt wird, leiten Sie um stdoutund stderrzu /dev/null:

(ls x.txt >> /dev/null 2>&1 && echo yes) || echo no
Philip Kirkbride
quelle
1
Dieser Code bedeutet: "Wenn lserfolgreich, gibt es eine solche Datei, sonst gibt es keine". Wenn dies lsfehlschlägt, bedeutet dies nicht, dass die Datei fehlt. Es könnte ein anderer Fehler sein. Erstellen Sie beispielsweise eine Datei in einem Verzeichnis, das root gehört, und versuchen Sie dies lsunter einem normalen Benutzer. Es wird mit fehlschlagen Permission denied, was nicht gleichbedeutend ist, dass die Datei nicht existiert.
Tigran
9

Hintergrund meiner Lösungsempfehlung ist die Geschichte eines Freundes, der bis weit in die zweite Woche seines ersten Jobs einen halben Build-Server sauber gewischt hat. Die grundlegende Aufgabe besteht also darin, herauszufinden, ob eine Datei vorhanden ist, und wenn ja, löschen wir sie. Aber es gibt ein paar tückische Stromschnellen an diesem Fluss:

  • Alles ist eine Datei.

  • Skripte haben nur dann echte Leistung, wenn sie allgemeine Aufgaben lösen

  • Um allgemein zu sein, verwenden wir Variablen

  • In Skripten wird häufig -f force verwendet, um manuelle Eingriffe zu vermeiden

  • Und auch Liebe -r rekursiv, um sicherzustellen, dass wir rechtzeitig erstellen, kopieren und zerstören.

Stellen Sie sich das folgende Szenario vor:

Wir haben die Datei, die wir löschen möchten: filesexists.json

Dieser Dateiname wird in einer Variablen gespeichert

<host>:~/Documents/thisfolderexists filevariable="filesexists.json"

Wir haben auch eine Pfadvariable, um die Dinge wirklich flexibel zu machen

<host>:~/Documents/thisfolderexists pathtofile=".."

<host>:~/Documents/thisfolderexists ls $pathtofile

filesexists.json  history20170728  SE-Data-API.pem  thisfolderexists

Mal sehen, ob -ees das tut, was es soll. Existieren die Dateien?

<host>:~/Documents/thisfolderexists [ -e $pathtofile/$filevariable ]; echo $?

0

Es tut. Magie.

Was würde jedoch passieren, wenn die Dateivariable versehentlich als Nuffin ausgewertet würde?

<host>:~/Documents/thisfolderexists filevariable=""

<host>:~/Documents/thisfolderexists [ -e $pathtofile/$filevariable ]; echo $?

0

Was? Es soll mit einem Fehler zurückkehren ... Und dies ist der Anfang der Geschichte, wie dieser gesamte Ordner versehentlich gelöscht wurde

Eine Alternative könnte darin bestehen, speziell zu testen, was wir als "Datei" verstehen.

<host>:~/Documents/thisfolderexists filevariable="filesexists.json"

<host>:~/Documents/thisfolderexists test -f $pathtofile/$filevariable; echo $?

0

Die Datei existiert also ...

<host>:~/Documents/thisfolderexists filevariable=""

<host>:~/Documents/thisfolderexists test -f $pathtofile/$filevariable; echo $?

1

Dies ist also keine Datei, und vielleicht möchten wir nicht das gesamte Verzeichnis löschen

man test hat folgendes zu sagen:

-b FILE

       FILE exists and is block special

-c FILE

       FILE exists and is character special

-d FILE

       FILE exists and is a directory

-e FILE

       FILE exists

-f FILE

       FILE exists and is a regular file

...

-h FILE

       FILE exists and is a symbolic link (same as -L)
Lefty G Balogh
quelle
4

Intern muss der Befehl rm ohnehin auf
Dateiexistenz testen. Warum also einen weiteren Test hinzufügen? Einfach ausgeben

rm filename

und es wird danach weg sein, ob es dort war oder nicht.
Verwenden Sie rm -f, wenn Sie keine Nachrichten zu nicht vorhandenen Dateien wünschen.

Wenn Sie Maßnahmen ergreifen müssen, wenn die Datei NICHT vorhanden ist, müssen Sie dies selbst testen. Aufgrund Ihres Beispielcodes ist dies in diesem Fall nicht der Fall.

TG
quelle
1
Dies ist eigentlich eine ziemlich gültige Antwort für den Befehl rm. Für andere Befehle schlage ich vor, lieber mit -e zu testen.
Warhansen
Nur dass es nicht das ist, was die Frage stellt.
Buntstifte
1
Es ist sehr wichtig, was die Frage stellt, wenn Sie die gesamte Frage einschließlich des Teils "... und (wenn ja) ... löscht sie" lesen .
TG
1

Wenn Sie ein NFS verwenden, ist "Test" eine bessere Lösung, da Sie eine Zeitüberschreitung hinzufügen können, falls Ihr NFS ausfällt:

time timeout 3 test -f 
/nfs/my_nfs_is_currently_down
real    0m3.004s <<== timeout is taken into account
user    0m0.001s
sys     0m0.004s
echo $?
124   <= 124 means the timeout has been reached

Ein "[-e my_file]" - Konstrukt friert ein, bis das NFS wieder funktionsfähig ist:

if [ -e /nfs/my_nfs_is_currently_down ]; then echo "ok" else echo "ko" ; fi

<no answer from the system, my session is "frozen">
FCA69
quelle
testund [sind auch. Sie können auch timeoutmit verwenden [und testfriert auch ein, wenn NFS hängt.
andere Typ