it-swarm.com.de

Wie genau funktioniert "/ bin / ["?

Ich bin immer wieder überrascht, dass im Ordner /bin da ist ein [ Programm.

Wird das so genannt, wenn wir so etwas tun wie: if [ something ]?

Durch Aufrufen des [ Programm explizit in einer Shell fragt es nach einem entsprechenden ], und wenn ich die schließende Klammer bereitstelle, scheint es nichts zu tun, egal was ich zwischen die Klammern stecke.

Es ist unnötig zu erwähnen, dass die übliche Art, Hilfe zu einem Programm zu erhalten, nicht funktioniert, d. H. Weder man [ Noch [ --help funktioniert.

51
Bregalad

Die Aufgabe des Befehls [ Besteht darin, Testausdrücke auszuwerten. Es wird mit einem Exit-Status von 0 zurückgegeben (dh true ), wenn der Ausdruck in true und etwas anderes aufgelöst wird (was bedeutet ) false ) sonst.

Es ist nicht so, dass es nichts tut, es ist nur so, dass sein Ergebnis in seinem Exit-Status liegt. In einer Shell können Sie den Exit-Status des letzten Befehls in $? Für Bourne-ähnliche Shells oder $status In den meisten anderen Shells (fish/rc/es/csh/tcsh) ermitteln. ..).

$ [ a = a ]
$ echo "$?"
0
$ [ a = b ]
$ echo "$?"
1

In anderen Sprachen wie Perl wird der Exit-Status beispielsweise im Rückgabewert von system() zurückgegeben:

$ Perl -le 'print system("[", "a", "=", "a", "]")'
0

Beachten Sie, dass alle modernen Bourne-ähnlichen Shells (und fish) einen integrierten Befehl [ Haben. Die in /bin Wird normalerweise nur ausgeführt, wenn Sie eine andere Shell verwenden oder wenn Sie Dinge wie env [ foo = bar ] Oder find . -exec [ -f {} ] \; -print Oder den obigen Befehl Perl ausführen. .

Der Befehl [ Ist auch unter dem Namen test bekannt. Beim Aufruf als test ist kein abschließendes ] - Argument erforderlich.

Während Ihr System möglicherweise keine Manpage für [ Hat, hat es wahrscheinlich eine für test. Beachten Sie jedoch erneut, dass die Implementierung von /bin/[ Oder /bin/test Dokumentiert wird. Um mehr über das in Ihrer Shell integrierte [ Zu erfahren, sollten Sie stattdessen die Dokumentation für Ihre Shell lesen.

Weitere Informationen zum Verlauf dieses Dienstprogramms und zum Unterschied zum [[...]] Ksh-Testausdruck finden Sie unter weitere Fragen und Antworten hier .

64

Ich bin immer wieder überrascht, dass sich im Ordner /bin Ein Programm [ Befindet.

Sie haben Recht, überrascht zu sein. Dies ist einer der seltenen POSIX-Befehle mit dem Dienstprogramm null (:), Der die Konvention für zulässige Zeichendateien (Befehlssatz für tragbare Dateinamen) nicht berücksichtigt.

Heißt das, wenn wir so etwas machen wie: if [ something ]?

Genau, aber es kann auch ohne if verwendet werden.

Durch das explizite Aufrufen des Programms [ In einer Shell wird nach einem entsprechenden ] Gefragt, und wenn ich die schließende Klammer bereitstelle, scheint es nichts zu tun, egal was ich zwischen die Klammern einfüge.

Es macht nichts Sichtbares, aber es macht genau das Gleiche wie bei Verwendung mit if, d. H. Es setzt den Exit-Status auf 0 (wahr) oder irgendetwas anderes (falsch), je nachdem, was Sie in die Klammern setzen. Es ist (aus einem bestimmten Grund) dasselbe Verhalten wie der Befehl test; Der einzige Unterschied ist, dass es nach der Endung ] sucht. Siehe man test für Details.

Es ist unnötig zu erwähnen, dass die übliche Art, Hilfe zu einem Programm zu erhalten, nicht funktioniert, d. H. Weder man [ Noch [ --help Funktioniert.

Das hängt von Ihrem Betriebssystem ab. man [ Funktioniert definitiv für mich auf einigen gängigen Gnu/Linux-Distributionen, aber nicht auf Solaris.

[ --help Funktioniert möglicherweise oder nicht, abhängig von der Implementierung, da die Syntax ohnehin verletzt wird und die Endung ] Fehlen. Darüber hinaus schließt der POSIX-Standard für den Befehl test/[ alle Optionen explizit aus, einschließlich der Beendigung der Option --, Sodass beide [ --help ] und test --help müssen true zurückgeben und von Natur aus still sein. Beachten Sie, dass das, was Sie in die Klammern oder nach [ Setzen und wie Optionen aussehen (z. B. -f file, -n string Und dergleichen), nicht sind. Optionen aber Operanden .

Alle modernen Shell-Interpreter im Bourne-Stil (wie bash, ksh, dash und zsh, um nur einige zu nennen) implementieren das test/[ Internes Dienstprogramm als integriertes Dienstprogramm. Wenn Sie sie verwenden, ist die richtige Handbuchseite möglicherweise die der Shell, nicht die test.

Vor Unix System III (1981) hat die Bourne Shell das Dienstprogramm test nicht als integriertes Programm implementiert, sodass nur die Implementierung eines externen Binärbefehls verfügbar war. Bis Unix System III gab es weder einen Befehl [ (Intern oder eingebaut), also mussten Sie beispielsweise unter Unix Version 7 Folgendes eingeben:

if test something ; then
…

anstatt:

if [ something ] ; then
…
41
jlliagre

[ Ist eigentlich allgemeiner als test Befehl bekannt. Die typische Verwendung dieses Befehls besteht einfach darin, Ausdrücke auszuwerten und ihre Bedingung zurückzugeben - wahr oder falsch. Es wird häufig in if-then-else-fi - Anweisungen verwendet, obwohl es auch außerhalb von if -Anweisungen verwendet werden kann, um andere Befehle über die Shell-Operatoren && Oder || Bedingt auszuführen damit.

$ [ -e /etc/passwd  ] && echo "File exists"
File exists

$ test -e /etc/passwd && echo "File exists"
File exists

Insbesondere wird die Auswertung über den Exit-Status an andere Befehle übermittelt. Einige Programme geben möglicherweise den Exit-Status aus, um verschiedene Arten von Ereignissen anzuzeigen - erfolgreich abgeschlossenes Programm, Fehler eines bestimmten Typs während der Ausführung oder Syntaxfehler. Im Fall des Befehls test gibt es 0 Bedeutet wahr und 1 Bedeutet falsch. Wie Stephan betonte, erzeugen Syntaxfehler den Exit-Status 2.

Der Speicherort hängt von Ihrem System ab und erklärt auch, warum Sie die Manpage nicht gesehen haben, als Sie man [ Ausgeführt haben. Unter FreeBSD steht es beispielsweise unter /bin. Unter Linux (oder in meinem speziellen Fall Ubuntu 16.04) ist es in /usr/bin/. Wenn Sie man [ Oder man test Auf einem Linux-System ausführen, wird dieselbe Dokumentation geöffnet. Es ist auch wichtig zu beachten, dass Ihre Shell möglicherweise eine eigene Implementierung von test hat.

Es sollte auch beachtet werden, dass dieser Befehl Probleme hat, die Korn Shells Implementierung (allgemein bekannt als "bedingter Ausdruck" Referenz mit doppelten eckigen Klammern, [[ "$USER" = "root" ]]). versucht zu lösen. Diese Funktion wird auch von anderen Shells wie bash und zsh verwendet.

10

Weder man [ Noch [ --help Funktionieren

In einigen Distributionen (z. B. Ubuntu) folgt man [ Einem Symlink zu test(1). Bei anderen (z. B. Arch) ist dies nicht der Fall. (Aber die test Manpage dokumentiert auch die Verwendung von [)


type -a [ Zeigt Ihnen, dass sowohl eine Shell als auch eine ausführbare Datei eingebaut sind.

$ type -a [
[ is a Shell builtin
[ is /usr/bin/[

bash-builtin [ --help gibt nur eine Fehlermeldung aus. (Da es sich jedoch um eine integrierte Version handelt, können Sie help [ Verwenden oder die Bash-Manpage/-Dokumente anzeigen.).

/usr/bin/[ --help Gibt die vollständige Hilfeausgabe aus (für die GNU Coreutils-Version), die mit Folgendem beginnt:

$ /usr/bin/[ --help
Usage: test EXPRESSION
  or:  test
  or:  [ EXPRESSION ]
  or:  [ ]
  or:  [ OPTION
Exit with the status determined by EXPRESSION.

      --help     display this help and exit
      --version  output version information and exit

und beschreibt dann die zulässige Syntax für EXPRESSION.

Auf diese Weise hätten Sie auch herausfinden können, dass [ Und test gleichwertig sind.


Übrigens, wenn Sie für Bash programmieren (oder interaktiv Einzeiler schreiben), würde ich [[ Anstelle von [ Empfehlen. Es ist in mehrfacher Hinsicht besser, siehe Links in Sergs Antwort.

3
Peter Cordes

Der Befehl [ gibt den Exit-Status Null zurück, wenn der in seinen Argumenten enthaltene Ausdruck als wahr und der Exit-Status ungleich Null als falsch angesehen wird, wenn der in seinen Argumenten enthaltene Ausdruck als falsch angesehen wird. Es schlägt auch mit einer Fehlermeldung fehl, wenn das letzte Argument nicht ] ist (dies erfolgt ausschließlich aus ästhetischen Gründen).

Z.B.:

[ hello ]
echo "Exit-status of [ hello ] is:" $?
[ abc = abc ]
echo "Exit-status of [ abc = abc ] is:" $?
[ ]
echo "Exit-status of [ ] is:" $?
[ abc = def ]
echo "Exit-status of [ abc = def ] is:" $?

… Gibt aus:

 Der Exit-Status von [Hallo] ist: 0  - da eine nicht leere Zeichenfolge als wahr angesehen wird  
 Exit-Status von [abc = abc] ist: 0  - weil 'abc' wirklich dasselbe ist wie 'abc'  
 Exit-Status von [] ist: 1  - weil leere Zeichenfolge als falsch betrachtet wird  
 Der Exit-Status von [abc = def] ist: 1  - weil 'abc' sich wirklich von 'def' unterscheidet 

Allerdings rufen bash und viele andere Shells in diesen Fällen normalerweise nicht /bin/[ (oder /usr/bin/[) auf, sondern rufen den eingebauten Befehl mit auf genau das gleiche Verhalten stattdessen (rein aus Leistungsgründen). Um /bin/[ (kein in Shell integrierter Ersatz) aufzurufen, müssen Sie entweder den Pfad explizit angeben (z. B. /bin/[ hello ]);; Sie müssen ] jedoch nicht mit dem Direktnamen ☺ voranstellen) oder um Shell so zu konfigurieren, dass kein integrierter Ersatz verwendet wird (z. B. enable -n [ in bash).

P. S.: Wie in anderen Antworten gesagt wurde, ist [ mit test verwandt. Aber test benötigt im Gegensatz zu [ nicht ] als letztes Argument (und erwartet es überhaupt nicht; das Hinzufügen zusätzlicher ] zu test Argumenten kann dazu führen, dass es mit einer Fehlermeldung fehlschlägt oder ein falsches Ergebnis zurückgibt)/bin/test und /bin/[ können in dieselbe Datei aufgelöst werden (z. B. ist eine symlinked ; In diesem Fall wird die Verhaltensumleitung wahrscheinlich durch Analyse des aktuell aufgerufenen Befehls innerhalb des test/[ Codes selbst) oder in verschiedene Dateien implementiert. Für test ruft Shell normalerweise auch einen integrierten Ersatz auf, es sei denn, der Pfad ist explizit angegeben (/bin/test) oder es ist so konfiguriert, dass dies nicht der Fall ist (enable -n test).

P. P. S.: Im Gegensatz zu test und [ ist modern if niemals eine echte Datei. Es ist Teil der Shell-Syntax (z. B. Bash): if commandA; then commandB; fi (Zeilenumbrüche können anstelle von Semikolons verwendet werden) bewirkt, dass commandB nur dann ausgeführt wird, wenn commandA beendet wird mit Nullstatus. Dies passt perfekt zum Verhalten von test oder [ und ermöglicht es, sie wie if [ "$a" = foo ]; then …; fi zu kombinieren (oder if test "$a" = foo; then …; fi - nur weniger lesbar). Moderne Skripte verwenden jedoch häufig [[ anstelle von test oder [, was (als if) niemals eine echte Datei ist, sondern immer eine Teil der Shell-Syntax.

P. P. P. S.: Was man betrifft - erwarten Sie niemals, dass man einen Artikel zu jedem Befehl in Ihrem Dateisystem enthält. Informationen zu einigen (sogar "echten", dateibasierten) Befehlen fehlen möglicherweise. Informationen zu einigen integrierten Shell-Funktionen sind möglicherweise nicht nur in einem Artikel enthalten, der einer bestimmten Shell gewidmet ist (an dieser Stelle finden Sie mit Sicherheit Informationen zu test, [, if, [[). Dennoch haben viele Distributionen explizite man- Artikel für test und [. (Über --help wird es aus offensichtlichen Gründen mit test nicht erkannt: Es muss leise Fälle wie a=--help; test "$a" behandeln; bei einigen Distributionen [ --help ( ohne ]) zu schließen, zeigt immer noch Hilfe, bei einigen nicht.)

2
sasha