让 bash 使用外部 `time` 命令而不是 shell 内置命令

让 bash 使用外部 `time` 命令而不是 shell 内置命令

如何让 bash 默认使用时间二进制文件 (/usr/bin/time) 而不是 shell 关键字?

which timereturns /usr/bin/time
type timereturnstime is a shell keyword
运行time显然是在执行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回报bash: enable: time: not a shell builtin

答案1

您可以使用command内置的 shell 来绕过正常的查找过程,并将给定的命令作为外部命令运行,而不管任何其他可能性(shell 内置命令、别名等)。这通常是在需要跨系统移植的脚本中完成的,尽管可能更常见地使用速记\(如\rm而不是command rmrm,特别是后者可能被别名为未知的东西,如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 (后者对于系统上的所有用户来说是全局的)。

对于相反的情况(强制使用内置的 shell,以防定义了别名),您可以使用类似的东西builtin time,它再次覆盖通常的搜索过程并运行指定的内置 shell。 bash 手册页提到,这通常用于cd通过名为 的函数提供自定义功能cd,而该函数又使用内置函数cd来执行实际操作。

答案2

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

答案3

内置函数(例如测试)的一般解决方案是[1]

  • 使用env(所有 shell)

    $ 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
    
  • 使用任意斜杠/调用命令(所有 shell):

    $ test 1 = 1 && echo "yes"
    yes 
    $ ~/bin/test
    external test
    
  • 创建别名(在 bash 脚本中失败,除非shopt -s expand_aliases使用 if ):

    $ 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

答案4

您可以使用该enable命令禁用某些内置命令。

$ enable -n kill

然而这time是一个关键字,所以这不起作用。

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

因此,您需要创建一个别名来覆盖它:

$ alias time=/usr/bin/time

相关内容