Ich versuche, ein einfaches Skript zu schreiben, das mir sagen wird, ob in $ Temp ein Dateiname existiert, der mit der Zeichenfolge "Test" beginnt.
Zum Beispiel habe ich diese Dateien
%Vor%Dann möchte ich nur ein Echo geben, dass eine Datei gefunden wurde.
Zum Beispiel so etwas:
%Vor%Aber das funktioniert nicht.
Ein Ansatz:
%Vor%Erläuterung:
shopt -s nullglob
bewirkt, dass /home/edward/bank1/fiche/Test*
auf nothing erweitert wird, wenn keine Datei mit diesem Muster übereinstimmt. (Ohne es wird es intakt bleiben.) ( ... )
richtet eine Untershell ein und verhindert, dass shopt -s nullglob
"entweicht". files=(/home/edward/bank1/fiche/Test*)
setzt die Dateiliste in ein Array mit dem Namen files
. (Beachten Sie, dass dies nur innerhalb der Untershell ist; auf files
kann nicht zugegriffen werden, nachdem die Untershell beendet wurde.) "${#files[@]}"
ist die Anzahl der Elemente in diesem Array. Bearbeitet um folgende Frage zu beantworten ("Was ist, wenn ich auch überprüfen muss, ob diese Dateien Daten enthalten und keine Null-Byte-Dateien sind"):
Für diese Version müssen wir -s
verwenden (wie Sie es in Ihrer Frage getan haben), die auch auf die Existenz der Datei testet. Es macht also keinen Sinn mehr shopt -s nullglob
zu verwenden: Wenn keine Datei dem Muster entspricht, dann -s
auf dem Muster wird falsch sein. Also können wir schreiben:
(Hier ist ( ... )
, um zu verhindern, dass file
und found_file
"entweichen".)
Sie können es in einer Zeile tun:
%Vor%Um zu verstehen, was es tut, müssen Sie den Befehl zerlegen und ein grundlegendes Bewusstsein für boolesche Logik haben.
Direkt von der Bash-Manpage:
%Vor%In der Shell (und allgemein in der Unix-Welt) ist der Boolesche Wert true ein Programm, das mit dem Status 0 endet.
ls
versucht, das Muster aufzulisten, wenn es erfolgreich ist (dh das Muster existiert), wird es mit dem Status 0, 2 beendet (andernfalls siehe ls man-Seite für Details).
In unserem Fall gibt es tatsächlich 3 Ausdrücke, aus Gründen der Klarheit werde ich Klammern setzen, obwohl sie nicht benötigt werden, weil &&
auf ||
Vorrang hat:
Wenn ausdruck1 also wahr ist (dh ls
hat das Muster gefunden), wird ausdruck2 ausgewertet (was nur ein Echo ist und mit dem Status 0 endet). In diesem Fall wird expression3 niemals ausgewertet, da das, was sich auf der linken Seite von ||
befindet, bereits wahr ist und es eine Verschwendung von Ressourcen wäre, zu versuchen, zu bewerten, was rechts ist.
Andernfalls, wenn Ausdruck1 falsch ist, wird Ausdruck2 nicht ausgewertet, aber in diesem Fall ist Ausdruck3.
Sie müssen verstehen, wie Unix Ihre Eingabe interpretiert.
Die Standard-Unix-Shell interpoliert Umgebungsvariablen und sogenannte globs , bevor sie die Parameter an Ihr Programm übergibt. Dies unterscheidet sich ein wenig von Windows, wodurch das Programm die Erweiterung interpretiert.
Versuchen Sie Folgendes:
%Vor% Dies wird alle Dateien und Verzeichnisse in Ihrem aktuellen Verzeichnis wiedergeben. Bevor der Befehl echo
ausgeführt wird, interpoliert die Shell die *
und erweitert sie und übergibt diesen erweiterten Parameter dann an Ihren Befehl. Sie können es in Aktion sehen, indem Sie dies tun:
Das set -xv
schaltet xtrace und verbose ein. Verbose gibt den eingegebenen Befehl zurück und xtrace gibt den Befehl zurück, der ausgeführt wird (dh nach der Shell-Erweiterung).
Versuchen Sie Folgendes:
%Vor%Beachten Sie, dass durch das Einfügen von Anführungszeichen in den Anführungszeichen der Glob-Ausdruck aus der Shell ausgeblendet wird und die Shell sie nicht erweitern kann. Versuchen Sie Folgendes:
%Vor%Beachten Sie, dass die Shell Umgebungsvariablen immer noch in doppelte Anführungszeichen, aber nicht in einfache Anführungszeichen erweitern kann.
Sehen wir uns nun Ihre Aussage an:
%Vor% Die doppelten Anführungszeichen verhindern, dass die Shell den Glob-Ausdruck erweitert, sodass file
gleich dem Literal home/edward/bank1/finche/Test*
ist. Daher müssen Sie dies tun:
Das Fehlen von Anführungszeichen (und der einleitende Schrägstrich, der wichtig ist!) macht jetzt die Datei gleich mit allen Dateien, die mit diesem Ausdruck übereinstimmen. (Es könnte mehr als eins sein!). Wenn es keine Dateien gibt, kann die Shell, abhängig von der Shell und ihren Einstellungen, die Datei einfach auf diese literale Zeichenfolge setzen.
Sie haben sicherlich die richtige Idee:
%Vor% Sie können jedoch immer noch gefunden keine zurückgeben, wenn mehr als eine Datei vorhanden ist. Stattdessen erhalten Sie möglicherweise einen Fehler in Ihrem test
-Befehl, weil zu viele Parameter vorhanden sind.
Eine Möglichkeit, dies zu umgehen, könnte sein:
%Vor% In diesem Fall nutze ich den Exit-Code des Befehls ls
. Wenn ls
eine Datei findet, auf die es zugreifen kann, gibt es einen Null-Exit-Code zurück. Wenn keine übereinstimmende Datei gefunden werden kann, wird ein Beendigungscode ungleich null zurückgegeben. Der Befehl if
führt lediglich einen Befehl aus, und wenn der Befehl eine Null zurückgibt, nimmt er die if
-Anweisung als true an und führt die if
-Klausel aus. Wenn der Befehl einen Wert ungleich null zurückgibt, wird die if
-Anweisung als falsch angenommen und die else
-Klausel (falls eine verfügbar ist) wird ausgeführt.
Der Befehl test
funktioniert in ähnlicher Weise. Wenn test
wahr ist, gibt der Befehl test
eine Null zurück. Andernfalls gibt der Befehl test
einen Wert ungleich null zurück. Das funktioniert großartig mit dem Befehl if
. Tatsächlich gibt es einen Alias für den Befehl test
. Versuchen Sie Folgendes:
Der i
gibt den Inode aus. Der inode ist die echte ID der Datei. Dateien mit derselben ID sind dieselbe Datei. Sie können sehen, dass /bin/test
und /bin/[
derselbe Befehl sind. Dies macht die folgenden zwei Befehle gleich:
Das folgende Skript hilft Ihnen, zu einem Prozess zu gehen, wenn dieses Skript in einer angegebenen Variablen existiert,
%Vor% hier -e
dient zum Arbeiten mit Dateien,
ist eine Shell-Variable,
Schlaf für 10 Minuten
Sie können das Skript nach ./waitfor.csh ./temp ; echo "the file exits"
Platzhalter werden nicht innerhalb von Strings in Anführungszeichen erweitert. Und wenn Wildcard erweitert wird, wird es unverändert zurückgegeben, wenn keine Übereinstimmungen vorhanden sind. Es wird nicht in eine leere Zeichenfolge erweitert. Probieren Sie:
%Vor% Wenn der Platzhalter zu Dateinamen erweitert wurde, zeigt ls
sie auf stdout
; Andernfalls wird ein Fehler in stderr
und nichts in stdout ausgegeben. Der Inhalt von stdout
wird output
zugewiesen.
if [ -n "$output" ]
prüft, ob $output
etwas enthält.
Eine andere Möglichkeit dies zu schreiben wäre:
%Vor%Tags und Links shell