Lassen Sie bash den externen Befehl `time` anstelle der eingebauten Shell verwenden

27

Wie kann ich dafür sorgen, dass Bash Time Binary (/ usr / bin / time) anstelle des Shell-Schlüsselworts verwendet?

which timereturns /usr/bin/time
type timereturns time is a shell keyword
Running timeführt offensichtlich das Shell-Schlüsselwort aus:

$ time

real    0m0.000s
user    0m0.000s
sys     0m0.000s
$ /usr/bin/time
Usage: /usr/bin/time [-apvV] [-f format] [-o file] [--append] [--verbose]
   [--portability] [--format=format] [--output=file] [--version]
   [--quiet] [--help] command [arg...]

enable -n time kehrt zurück bash: enable: time: not a shell builtin

David Holdeman
quelle

Antworten:

30

Sie können die commandeingebaute Shell verwenden, um den normalen Suchvorgang zu umgehen und den angegebenen Befehl als externen Befehl auszuführen, unabhängig von anderen Möglichkeiten (eingebaute Shell, Aliase usw.). Dies geschieht häufig in Skripten, die systemübergreifend portierbar sein müssen, obwohl wahrscheinlich häufiger die Kurzform verwendet wird \(wie in \rmund nicht command rmoder rm, da insbesondere letztere auf etwas ausgerichtet sein können, das nicht bekannt ist wie rm -i).

$ time

real    0m0.000s
user    0m0.000s
sys 0m0.000s
$ command time
Usage: time [-apvV] [-f format] [-o file] [--append] [--verbose]
       [--portability] [--format=format] [--output=file] [--version]
       [--quiet] [--help] command [arg...]
$ 

Dies kann mit einem Alias ​​wie folgt verwendet werden:

$ alias time='command time'
$ time
Usage: time [-apvV] [-f format] [-o file] [--append] [--verbose]
       [--portability] [--format=format] [--output=file] [--version]
       [--quiet] [--help] command [arg...]
$ 

Der Vorteil gegenüber z. B. alias time=/usr/bin/timeist, dass Sie nicht den vollständigen Pfad zur timeBinärdatei angeben, sondern stattdessen auf den üblichen Pfadsuchmechanismus zurückgreifen.

Der aliasBefehl selbst kann zB in ~ / .bashrc oder /etc/bash.bashrc abgelegt werden (letzteres ist global für alle Benutzer im System).

Für den umgekehrten Fall (Erzwingen der Verwendung der integrierten Shell, falls ein Alias ​​definiert ist) würden Sie so etwas wie verwenden builtin time, das wiederum den üblichen Suchprozess außer Kraft setzt und die integrierte benannte Shell ausführt. In der Bash-Manpage wird erwähnt, dass dies häufig verwendet wird, um benutzerdefinierte cdFunktionen mit einer Funktion namens bereitzustellen cd, die wiederum die eingebaute Funktion verwendet cd, um die eigentliche Aufgabe zu erledigen.

ein CVn
quelle
Sie können mit dem Befehl auch nachfragen, woher ein bestimmter Befehl stammt type -a <cmd>.
SLM
12
commandumgeht keine Builtins (außer zshwenn keine anderen Shells emuliert werden). Es umgeht Funktionen und das ist der Hauptgrund für seine Existenz. Seine zweite Aufgabe ist es, das Besondere an besonderen Einbauten zu entfernen . Aliase und Schlüsselwörter werden nur zshumgangen, weil diese nur an erster Stelle erweitert werden ( z. B. werden globale Aliase nicht umgangen). Es ist keine timeBash eingebaut. timeist ein Schlüsselwort, das Sie zum Beispiel tun können time { foo; bar; }.
Stéphane Chazelas
1
@StephaneChazelas Fühlen Sie sich auf jeden Fall frei, dies in die Antwort zu schreiben, um eine genauere Beschreibung zu erhalten. commandfunktioniert in diesem speziellen Fall, wie am Beispiel gezeigt, aber offensichtlich ist eine richtige Antwort besser als eine halb richtige.
ein
1
Der letzte Teil Ihrer Antwort ist falsch. time ist keine eingebaute Shell, sondern ein Shell-Schlüsselwort. builtin timefunktioniert nicht
Teresa e Junior
ähnlich wie befehl wäre es nur zu zitieren:'time' echo test
mxmlnkn
9

Es gibt eine Abkürzung in Bash, um Schlüsselwörter zu umgehen, ohne einen Pfad angeben oder einen anderen eingebauten verwenden zu müssen, wie command: Escape mit einem Backslash.

=^_^= izkata@Izein:~$ time

real    0m0.000s
user    0m0.000s
sys     0m0.000s
=^_^= izkata@Izein:~$ \time
Usage: time [-apvV] [-f format] [-o file] [--append] [--verbose]
       [--portability] [--format=format] [--output=file] [--version]
       [--quiet] [--help] command [arg...]

Persönlich finde ich das lesbarer und sicherer, da dies möglich ist:

=^_^= izkata@Izein:~$ alias command=echo
=^_^= izkata@Izein:~$ command time
time
Izkata
quelle
8
Beachten Sie, dass jede Form von zitieren oder alles , was es macht nicht das Token timetun: ti\me, 'time', ti""me, ti${-##*}me, ${-+time}... Das gilt für jede Shell - Schlüsselwort.
Stéphane Chazelas
Beste PS1, die ich je gesehen habe.
Maxywb
1
@maxywb Außerdem ist es nicht nur dekorativ - wenn der letzte Befehl fehlschlägt, verwandelt sich das glückliche Gesicht in ein rotes(x_x)
Izkata
4

Die allgemeinen Lösungen für integrierte Funktionen (zum Beispiel Test) sind [1] :

  • Verwenden Sie env(alle Muscheln)

    $ env test
    external test
  • deaktiviere das eingebaute (nur bash und zsh):

    $ test 1 = 1 && echo "yes"
    yes
    $ enable -n test        ### for bash. Re-enable with "enable test".
    $ disable test          ### for zsh. Re-enable with "enable test".
    $ test
    external test
  • Verwenden Sie einen beliebigen Schrägstrich /, um den Befehl aufzurufen (alle Shells):

    $ test 1 = 1 && echo "yes"
    yes 
    $ ~/bin/test
    external test
  • Erstelle einen Alias ​​(schlägt in einem Bash-Skript fehl, außer wenn shopt -s expand_aliasesverwendet):

    $ alias test='~/bin/test'             ### remove with 'unalias test'.
    $ test
    external test

Aber die Zeit ist nicht eingebaut.

Das Wort timeist ein "reserviertes Wort", kein Befehl und auch kein eingebautes Wort. Das ermöglicht diese Lösungen:

  • Zitiere das Wort. Dies funktioniert nicht mit eingebauten Funktionen.
    Viele Formen der Zitierarbeit: \time "time" 'time' ti\me ti"me"usw.

    $  time
    
    real    0m0.000s
    user    0m0.000s
    sys     0m0.000s
    
    $ \time
    Usage: /usr/bin/time [-apvV] [-f format] [-o file] [--append] [--verbose]
           [--portability] [--format=format] [--output=file] [--version]
           [--quiet] [--help] command [arg...]

    Dies ist nützlich, um einen Alias ​​zu umgehen. Auch wenn testein Alias ​​vorliegt, \testwird der Befehl PATHed ausgeführt (oder der eingebaute Befehl, falls er nicht deaktiviert wurde).

  • Verwenden Sie das eingebaute command(dies funktioniert nicht mit eingebauten):

    $ command time
  • Wie oben für eingebaute Funktionen, mit beliebigen Schrägstrichen /:

    $ /usr/bin/time
  • Wie oben bei den eingebauten Funktionen funktioniert auch hier ein Alias:

    $ alias time='command time'
    $ alias time='/usr/bin/time'

[1] Nehmen wir an, es gibt eine externe ausführbare Datei ~/bin/test, die "external test" ausgibt. Und weiter: Nehmen wir an, dass wir im aktiven PATH einen ~/binVorsprung haben /bin.


quelle
2

Legen Sie dies in Ihrem ~/.bashrc:

alias time=/usr/bin/time

TravisThomas
quelle
2

Mit dem enableBefehl können Sie bestimmte integrierte Funktionen deaktivieren.

$ enable -n kill

Da timees sich jedoch um ein Schlüsselwort handelt, funktioniert dies nicht.

$ builtin time
bash: builtin: time: not a shell builtin

Sie müssen also einen Alias ​​erstellen, um ihn zu überschreiben:

$ alias time=/usr/bin/time
slm
quelle
Nee. time ist ein Shell-Schlüsselwort, keine eingebaute Shell. Ich wollte gerade meine Frage bearbeiten, um zu sagen, dass enable -n nicht funktioniert, als ich sah, dass Sie geantwortet hatten.
David Holdeman