Как улучшить встроенную функцию оболочки, все еще используя ее - PullRequest
1 голос
/ 09 апреля 2020

В большинстве случаев мне нравится не только видеть, где находится указанная команда c, но и что это такое. Пример which lsd говорит мне, что эта команда действительна и существует в /usr/local/bin/lsd, но более интересная информация: это ссылка на ../Cellar/lsd/0.16.0/bin/lsd, которая сообщает мне, что это команда, управляемая homebrew.

Итак чтобы увидеть оба, я хотел создать псевдоним. Но, похоже, псевдоним не подходит для аргументов и даже для простых команд, которые могут работать, я не заставлял его работать со встроенным выполнением команд, например $(which $1). Затем я создал функцию оболочки для правильного использования параметра команды:

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

Эта функция делает то, что я хотел:

enter image description here

за исключением одного: я должен запомнить имя функции и использовать его вместо which. Поэтому я попытался наложить псевдоним на эту функцию, но он производит странные вещи, так как это приводит к рекурсивному вызову самого себя - так что это плохо. Поскольку это не команда, я также не могу использовать ее точное местоположение, чтобы опустить эту «ошибку».

Поэтому вопрос : Как я могу заменить функцию внутренней оболочки which на мою собственная функция, которая по-прежнему использует значение по умолчанию 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
}

enter image description here

1 Ответ

1 голос
/ 09 апреля 2020

Непосредственное решение вашего вопроса "как выбрать 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 псевдоним, который обычно отключается в неинтерактивных оболочках (например, при запуске скрипта); Вероятно, он будет запущен в интерактивном сеансе, где определено ll. Просто знайте, что если вы используете его в сценарии, вам лучше использовать ls -l вместо ll псевдоним.

...