Faire en sorte que bash utilise la commande externe `time` plutôt que le shell intégré

27

Comment puis-je faire en sorte que bash utilise le temps binaire (/ usr / bin / time) par défaut au lieu du mot-clé shell?

which timerenvoie /usr/bin/time
type timeretour La time is a shell keyword
course timeest évidemment en train d'exécuter le mot clé shell:

$ 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 résultats bash: enable: time: not a shell builtin

David Holdeman
la source

Réponses:

30

Vous pouvez utiliser le commandshell intégré pour contourner le processus de recherche normal et exécuter la commande donnée en tant que commande externe indépendamment de toute autre possibilité (shell intégré, alias, etc.). Cela se fait souvent dans des scripts qui doivent être portables sur tous les systèmes, bien que probablement plus couramment en utilisant la sténographie \(comme dans \rmplutôt que command rmou rm, car en particulier ce dernier peut être aliasé à quelque chose de non connu comme 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...]
$ 

Cela peut être utilisé avec un alias, comme ceci:

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

L'avantage de ceci par exemple, alias time=/usr/bin/timec'est que vous ne spécifiez pas le chemin complet vers le timebinaire, mais que vous retombez plutôt sur le mécanisme de recherche de chemin habituel.

La aliascommande elle-même peut aller par exemple dans ~ / .bashrc ou /etc/bash.bashrc (cette dernière est globale pour tous les utilisateurs du système).

Dans le cas contraire (forcer l'utilisation du shell intégré au cas où un alias est défini), vous utiliseriez quelque chose comme builtin time, qui outrepasse le processus de recherche habituel et exécute le shell nommé intégré. La page de manuel bash mentionne que cela est souvent utilisé afin de fournir des cdfonctionnalités personnalisées avec une fonction nommée cd, qui à son tour utilise le module intégré cdpour faire la chose réelle.

un CVn
la source
Vous pouvez également demander d'où provient une commande particulière à l'aide de la commande type -a <cmd>.
slm
12
commandne contourne pas les builtins (sauf zshquand ils n'émulent pas d'autres shells). Il contourne les fonctions et c'est la principale raison de son existence. Son deuxième rôle est de supprimer le spécial dans les buildins spéciaux . Il contourne les alias et les mots clés uniquement parce que ceux-ci ne sont développés qu'en première position ( zshpar exemple, il ne contourne pas les alias globaux). Il n'y a pas de timebash intégré. timeest un mot-clé que vous pouvez faire par exemple time { foo; bar; }.
Stéphane Chazelas
1
@StephaneChazelas N'hésitez pas à le modifier dans la réponse pour fournir une description plus précise. commandfonctionne dans ce cas particulier, comme illustré, mais de toute évidence, une bonne réponse vaut mieux qu'une demi-droite.
un CVn
1
La dernière partie de votre réponse est fausse. le temps n'est pas un shell intégré, mais plutôt un mot clé shell. builtin timene fonctionne pas.
Teresa e Junior
similaire à la commande serait de simplement le citer:'time' echo test
mxmlnkn
9

Il y a un raccourci dans bash pour contourner les mots-clés, sans avoir à spécifier un chemin ou à utiliser un autre module intégré comme command: Échapper avec une barre oblique inverse.

=^_^= 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...]

Personnellement, je trouve cela plus lisible et plus sûr, car c'est possible:

=^_^= izkata@Izein:~$ alias command=echo
=^_^= izkata@Izein:~$ command time
time
Izkata
la source
8
Notez que toute forme de citation ou tout ce qui en fait pas le jeton timefera: ti\me, 'time', ti""me, ti${-##*}me, ${-+time}... qui dénomme un mot - clé shell.
Stéphane Chazelas
La meilleure PS1 que j'ai jamais vue.
maxywb
1
@maxywb En outre, ce n'est pas seulement décoratif - si la dernière commande a échoué, le visage heureux devient rouge(x_x)
Izkata
4

Les solutions générales pour les modules intégrés (par exemple test) sont [1] :

  • utiliser env(tous les coquillages)

    $ env test
    external test
  • désactiver la fonction intégrée (uniquement bash et 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
  • utilisez n'importe quelle barre oblique /pour appeler la commande (tous les shells):

    $ test 1 = 1 && echo "yes"
    yes 
    $ ~/bin/test
    external test
  • créer un alias (échoue dans un script bash, sauf s'il shopt -s expand_aliasesest utilisé):

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

Mais le temps n'est pas intégré.

Le mot timeest un «mot réservé», pas une commande ni un intégré. Qui permettent ces solutions:

  • Citez le mot. Cela ne fonctionne pas avec les intégrés.
    De nombreuses formes de citation de travaux:, \time "time" 'time' ti\me ti"me"etc.

    $  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...]

    Ceci est utile pour contourner un alias. Même s'il testest aliasé, \testexécutera la commande PATHed (ou le module intégré s'il n'a pas été désactivé).

  • Utilisez la fonction intégrée command(cela ne fonctionne pas avec les fonctions intégrées):

    $ command time
  • Comme ci-dessus pour les intégrés, l'utilisation de toutes les barres obliques /fonctionne:

    $ /usr/bin/time
  • Comme ci-dessus pour les intégrés, un alias fonctionne également ici:

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

[1] Supposons qu'il existe un exécutable externe ~/bin/testqui imprime "test externe". Et plus loin: supposons que ce ~/binsoit en avance /bindans le PATH actif.


la source
2

Déposez ceci dans votre ~/.bashrc:

alias time=/usr/bin/time

TravisThomas
la source
2

Vous pouvez utiliser la enablecommande pour désactiver certains éléments intégrés.

$ enable -n kill

Cependant, timec'est un mot clé, donc cela ne fonctionnera pas.

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

Il vous reste donc à créer un alias pour le remplacer:

$ alias time=/usr/bin/time
slm
la source
Nan. time est un mot-clé shell, pas un shell intégré. J'étais sur le point de modifier ma question pour dire que enable -n ne fonctionne pas quand j'ai vu que vous aviez répondu.
David Holdeman