Как использовать `which` для команды с псевдонимом?

76

Как и у большинства пользователей, у меня есть набор псевдонимов, чтобы задать набор флагов по умолчанию для часто используемых программ. Например,

alias vim='vim -X'
alias grep='grep -E'
alias ls='ls -G'

Проблема в том, что если я хочу использовать, whichчтобы увидеть, откуда поступает мой vim/ grep/ ls/ etc, псевдоним мешает:

$ which vim
vim: aliased to vim -X

Это полезный вывод, но не то, что я ищу в этом случае; Я знаю, что vimэто псевдоним, vim -Xно я хочу знать, откуда это vim исходит.

Если не считать временного определения псевдонима, чтобы я мог использовать whichего, есть ли простой способ which«развернуть» псевдоним и запустить его самому?

Редактировать: Кажется, что whichэто встроенная оболочка с различным поведением в разных оболочках. В Bash предложение SiegeX о --skip-aliasфлаге работает; однако я на зш. Есть ли что-то подобное там?

Адриан Петреску
источник
в Zsh, если вы хотите знать, откуда это vimисходит , вы бы использовалиwhere vim
Matija Nalis

Ответы:

105

whichна самом деле это плохой способ делать такие вещи, так как он делает предположения о вашей среде на основе $SHELLи файлах запуска (которые он считает), которые использует оболочка; Мало того, что он иногда ошибается, но вы не можете сказать, что он ведет себя иначе. ( whichна моем Ubuntu 10.10 не понимает, --skip-aliasкак упомянуто, например, @SiegeX.) typeиспользует текущую среду оболочки вместо того, чтобы тыкать в ваши файлы конфигурации, и может быть сказано игнорировать части этой среды, поэтому он показывает вам, что на самом деле произойдет вместо того, что произойдет в реконструкции вашей оболочки по умолчанию.

В этом случае type -Pбудут обходиться любые псевдонимы или функции:

$ type -P vim
/usr/bin/vim

Вы также можете попросить его снять все слои, по одному, и показать вам, что он найдет:

$ type -a vim
vim is aliased to `vim -X'
vim is /usr/bin/vim

(Расширяя это из комментариев :)

Проблема в whichтом, что это обычно внешняя программа, а не встроенная оболочка, что означает, что она не может видеть ваши псевдонимы или функции и должна пытаться восстановить их из файлов запуска / конфигурации оболочки. (Если это встроенная оболочка, как она есть, zshно, по-видимому, нет bash, она с большей вероятностью использует среду оболочки и делает правильные вещи.)

typeэто POSIX-совместимая команда, которая должна вести себя так, как если бы она была встроенной (то есть она должна использовать среду оболочки, из которой вызывается, включая локальные псевдонимы и функции), поэтому обычно она является встроенной.

Обычно его нет в csh/ tcsh, хотя в большинстве современных версий whichон встроен в оболочку и делает все правильно; иногда whatвместо этого встроенный , а иногда нет никакого хорошего способа увидеть текущую среду оболочки из csh/ tcshвообще.

geekosaur
источник
6
Спасибо! Это что-то очень полезное, чтобы добавить к моей сумке трюков. Мне особенно нравится, что, type -aкажется, возвращает все экземпляры на вашем $PATH, а не только первый. Я думаю , что я буду псевдоним whichдля type:)
Адриан Петреску
2
@ geekosaur: Спасибо. Если typeэто часть стандарта POSIX, то это путь. Чтобы ответить на мой вопрос, тип работает и на zsh (на Debian). Почему дистрибутивы не избавляются whatи whichесли они не стандартизированы и не имеют дополнительной функциональности?
Фахим Митха
1
Нет, даже удаленно.
geekosaur
1
@Faheem: с документацией, я бы начал с info bash 'Bash builtins'Linux, хотя вы также можете найти ее в zshсправочном руководстве. Более официально, pubs.opengroup.org/onlinepubs/009695399/utilities/type.html (который я отмечаю, на самом деле не специфицируется -Pили -a, или даже -pявляется оригинальной формой -P, но требует использования текущей среды оболочки).
geekosaur
2
type -pведет себя по-разному между Zsh и Bash. type -Pвообще не существует в зш.
Кодзиро
15

В bash:

type -P vim

В zsh:

type -p vim

В обоих:

/usr/bin/which vim

Или же:

( unalias vim; type vim )
Mikel
источник
2
Последний классный У нас может быть псевдоним для этого. :)
балки
В bash на redhat я должен использовать тип -P, а не который, если я хочу правильный ответ. Никакие псевдонимы или функции не затрагиваются.
Доктор Эвал, который "который"? Какая красная шляпа?
Микель
@Mikel RH7.4. GNU который v2.20.
4

В zsh whichесть встроенная команда:

$ whence -w which
which: builtin

Чтобы выполнить внешнюю команду (в любой оболочке) which, используйте полный путь :

$ /bin/which ls; echo $?
/bin/ls
0

таким образом, команда lsбыла найдена (значение выхода 0) и расположена в /bin/ls.

Внутри zsh; способ (помимо приведенного выше) для поиска внешних команд :

$ whence -p ls
/bin/ls

Однако это не разрешит вложенные псевдонимы, такие как:

$ alias dire='ls -l'

Команда сообщит, что direкоманда не найдена.

$ whence -p dire; echo $?
1

Для разрешения вложенных псевдонимов (вручную) см. Resolve nested aliases to their source commands

HalosGhost
источник
2

Шахта определена как таковая

alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
Meitham
источник
1

Попробуйте следующее:

which --skip-alias vim
SiegeX
источник
1
Интересно! Это работает на Bash, но не на Zsh (я действительно не думал, что это будет зависеть от оболочки). Это заставило меня понять, что whichна самом деле это встроенная оболочка, а не обычная утилита Unix, как я предполагал. Поэтому я должен отредактировать свой вопрос и указать Zsh. Спасибо, что указал мне на это!
Адриан Петреску
whichне является встроенным, по крайней мере, в Debian. Это сценарий оболочки и часть debianutils, поэтому работает на zsh. Тем --skip-aliasне менее, это не вариант whichна Debian. Существуют ли различные варианты whichплавания вокруг? Это не похоже на стандартизированную команду.
Фахим Митха
@Faheem Mitha: это встроенный Zsh. См man zshbuiltins. имя которого [-wpams] ... Эквивалентно откуда -c.
Микель
Да, на Xubuntu bash, это не встроенный и не имеет --skip-aliasвозможности.
полим
На CentOS (и RHEL?) 6 это исполняемый файл /usr/bin/whichплюс псевдоним, /etc/profile.dкоторый позволяет обрабатывать псевдонимы, но --skip-aliasработает. В результате which whichпоказывает псевдоним, но command which whichпоказывает исполняемый файл!
dave_thompson_085
0

Другой альтернативой является command which vim, которая работает так же, как в zshиbash

Например, на моем Mac:

LOLcalhost :: ~ % command which grep
/usr/local/bin/grep
Зи Александр
источник
Ах достаточно справедливо.
Зи Александр
0

Оба typeи whichведут себя по-разному в зависимости от типа вашей оболочки.

В bash whichкоманда существует в PATH. Он ищет команду, которую вы указали PATH. Встроенный Bash type -P(P для PATH) ведет себя так же, как which.

В ZSH whichи typeесть встроенные функции, и частичные функции встроенных whence. which -pэто то, что вы хотите. Это заставляет поиск пути. ( -Pопция недоступна для typeZSH.)

откуда [-vcwfpamsS] [-x номер] имя ...

-п

Выполните поиск пути по имени, даже если это псевдоним, зарезервированное слово, функция оболочки или встроенная функция.

Больше из руководства ZSH.

имя которого [-wpamsS] [-x num] ...

Эквивалентно откуда -c.

Чтобы пропустить builtin whichи принудительно использовать команду whichиз PATHZSH:

alias which="command which"
Simba
источник