Заставьте bash использовать внешнюю команду `time` вместо встроенной оболочки


27

Как сделать так, чтобы bash по умолчанию использовал ключевое слово time (/ usr / bin / time) вместо ключевого слова shell?

which timeвозвращает /usr/bin/time
type timeвозвращается time is a shell keyword
Запуск time, очевидно, выполняет ключевое слово оболочки:

$ 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 возвращается bash: enable: time: not a shell builtin

Ответы:


30

Вы можете использовать commandвстроенную оболочку, чтобы обойти обычный процесс поиска и выполнить данную команду как внешнюю команду независимо от любых других возможностей (встроенные функции оболочки, псевдонимы и т. Д.). Это часто делается в сценариях, которые должны быть переносимы между системами, хотя, вероятно, чаще используют сокращение \(например, \rmвместо command rmили rm, так как последнее может быть связано с чем-то, что не известно как 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...]
$ 

Это можно использовать с псевдонимом, например так:

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

Преимущество этого перед, например, в alias time=/usr/bin/timeтом, что вы не указываете полный путь к timeдвоичному файлу , а вместо этого возвращаетесь к обычному механизму поиска пути.

Сама aliasкоманда может входить, например, в ~ / .bashrc или /etc/bash.bashrc (последняя является глобальной для всех пользователей системы).

В противоположном случае (принудительное использование встроенной оболочки в случае, если определен псевдоним), вы должны использовать что-то вроде этого builtin time, что снова отменяет обычный процесс поиска и запускает встроенную именованную оболочку. На странице руководства bash упоминается, что это часто используется для обеспечения пользовательских cdфункций с помощью названной функции cd, которая, в свою очередь, использует встроенную функцию cdдля реальной работы.


Вы также можете узнать, откуда поступает определенная команда, используя команду type -a <cmd>.
slm

12
commandне обходит встроенные функции (кроме случаев, zshкогда они не эмулируют другие оболочки). Он обходит функции, и это главная причина его существования. Его вторая роль состоит в том, чтобы удалить специальные в специальных встроенных функциях . Он обходит псевдонимы и ключевые слова только потому, что они раскрываются только в первой позиции ( zshнапример, он не обходит глобальные псевдонимы). Там нет timeвстроенного Bash. timeэто ключевое слово, так что вы можете сделать, например time { foo; bar; }.
Стефан Шазелас

1
@StephaneChazelas Во что бы то ни стало, не стесняйтесь редактировать это в ответ, чтобы дать более точное описание. commandработает в данном конкретном случае, как пример, но, очевидно, правильный ответ лучше, чем полуправильный.
CVn

1
Последняя часть вашего ответа неверна. время - это не встроенная оболочка, а ключевое слово оболочки. builtin timeне работает
Тереза ​​и Джуниор

похоже на команду будет просто процитировать его:'time' echo test
mxmlnkn

9

В bash есть ярлык, позволяющий обходить ключевые слова без указания пути или использования другого встроенного метода, например command: экранируйте его обратной косой чертой.

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

Лично я считаю это более читабельным и безопасным, поскольку это возможно:

=^_^= izkata@Izein:~$ alias command=echo
=^_^= izkata@Izein:~$ command time
time

8
Обратите внимание , что любая форма цитирования или что - нибудь , что делает его не маркер timeбудет делать: ti\me, 'time', ti""me, ti${-##*}me, ${-+time}... Это относится к любому ключевому слову оболочки.
Стефан Шазелас

Лучший PS1, который я видел.
maxywb

1
@maxywb Кроме того, это не просто декоративно - если последняя команда не удалась, счастливое лицо превращается в красное(x_x)
Izkata

4

Общие решения для встроенных модулей (например, test): [1] :

  • использовать env(все снаряды)

    $ env test
    external test
    
  • отключить встроенный (только bash и 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
    
  • используйте любую косую черту /для вызова команды (все оболочки):

    $ test 1 = 1 && echo "yes"
    yes 
    $ ~/bin/test
    external test
    
  • создать псевдоним (происходит сбой внутри скрипта bash, кроме случаев, когда shopt -s expand_aliasesон используется):

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

Но время не является встроенным.

Слово timeявляется «зарезервированным словом», а не командой и не является встроенным. Это позволяет это решения:

  • Процитируй слово. Это не работает со встроенными модулями.
    Многие формы цитирования работы: \time "time" 'time' ti\me ti"me"и т. Д.

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

    Это полезно для обхода псевдонима. Даже если с testпсевдонимом, \testвыполнит команду PATHed (или встроенную, если она не была отключена).

  • Используйте встроенный command(это не работает со встроенными модулями):

    $ command time
  • Как и выше для встроенных модулей, /работает любой слеш :

    $ /usr/bin/time
  • Как и выше для встроенных модулей, здесь также работает псевдоним:

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

[1] Предположим, что есть внешний исполняемый файл, ~/bin/testкоторый печатает «внешний тест». И еще: давайте предположим, что ~/binвпереди /binв активной PATH.



2

Вы можете использовать enableкоманду, чтобы отключить определенные встроенные модули.

$ enable -n kill

Однако timeэто ключевое слово, так что это не сработает.

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

Итак, вам осталось создать псевдоним для его переопределения:

$ alias time=/usr/bin/time

Нет. время - это ключевое слово оболочки, а не встроенная оболочка. Я как раз собирался отредактировать свой вопрос, чтобы сказать, что enable -n не работает, когда я увидел, что вы ответили.
Дэвид Холдеман
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.