首页 > 解决方案 > 如何在使用的同时增强内置的 shell 功能

问题描述

大多数时候 id 不仅喜欢查看特定命令的位置,还喜欢查看它是什么。一个例子which lsd告诉我这个命令是有效的并且存在于 中/usr/local/bin/lsd,但更有趣的信息是:它的一个链接../Cellar/lsd/0.16.0/bin/lsd告诉我它是一个由 homebrew 管理的命令。

所以要同时查看两者,我想创建一个别名。但是别名似乎不能很好地处理参数,甚至对于可能有效的简单命令,我没有让它与内联命令执行一起工作,例如$(which $1)。接下来我创建了一个shell函数来正确使用命令参数:

function dings() {
  command=`which $1`
  echo $command
  eval "$command --version" # might not be supported by all commands
  ll $command
}

这个功能有点像我想要的那样:

在此处输入图像描述

除了一件事:我必须记住函数名并使用它而不是which. 所以我尝试为该函数起别名,但他正在产生奇怪的东西,因为这会导致递归调用自身 - 这很糟糕。由于这不是命令,我也不能使用它的确切位置来省略这个“错误”。

所以问题是:如何which用我自己的仍然使用默认值的函数替换内部 shell 函数which

另外:我如何能够显示所有找到的相关命令实例?因此,就我而言,lsd我的系统中有两个版本。路径中的第一个是较旧的 brew 版本,路径中的第二个是cargo版本。

解决方案

function which() {
    IFS='
'
    set -f
    for LINE in `type -a $1`; do
        COMMAND=`echo $LINE | cut -d ' ' -f 3`
        if [[ $COMMAND = /* ]]; then
            version=`$COMMAND --version 2>/dev/null` # might not work with all commands
            [[ -n "$version" ]] && version="($version)"
            echo "$1 is $COMMAND $version"
            ll $COMMAND
        else
            echo $LINE
        fi
    done
}

在此处输入图像描述

标签: bashfunctionshellalias

解决方案


您的问题“我如何选择使用哪个”的直接解决方案是用于抑制 shell 函数查找which的内置函数:command

which() {
    command which "$1"
    "$1" --version
    ll "$(command which "$1")"
}

这也避免了不必要的eval并且不使用临时变量。如果要避免运行which两次,可以使用临时变量,但不要将其泄漏到环境中:

which() {
    local whichpath
    whichpath=$(command which "$1")
    printf '%s\n' "$whichpath"
    "$1" --version
    ll "$whichpath"
}

但是您可以完全避免使用外部命令which,而是使用内置命令type

type() {
    local typepath
    typepath=$(command type -p "$1")
    printf '%s\n' "$typepath"
    "$1" --version
    ll "$typepath"
}

请注意,如果您使用它来查找不是可执行文件的内容,这将中断。

或者,如果你真的想迷惑未来的自己,你可以调用函数which,但type在后台使用:

which() {
    local typepath
    typepath=$(type -p "$1")
    printf '%s\n' "$typepath"
    "$1" --version
    ll "$typepath"
}

旁注:这使用ll别名,通常在非交互式 shell 中禁用(例如在运行脚本时);不过,它很可能在ll定义的交互式会话中运行。只要知道,如果你要在脚本中使用它,你最好使用它ls -l而不是ll别名。


推荐阅读