Comment utiliser `which` sur une commande avec alias?

76

Comme la plupart des utilisateurs, de nombreux alias ont été configurés pour donner un ensemble d'indicateurs par défaut aux programmes fréquemment utilisés. Par exemple,

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

Le problème est que si je veux utiliser whichpour voir d'où vient mon vim/ grep/ ls/ etc, le pseudonyme est un obstacle:

$ which vim
vim: aliased to vim -X

C'est une sortie utile, mais pas ce que je recherche dans ce cas; Je sais que vimc'est un alias, vim -Xmais je veux savoir d'où ça vim vient.

À moins que l’alias ne soit temporairement non défini pour que je puisse l’utiliser which, existe-t-il un moyen facile d’avoir which«déballé» l’alias et de s’exécuter lui-même?

Edit: Il semble que ce whichsoit un shell intégré avec des comportements différents selon les différents shells. Dans Bash, la suggestion du --skip-aliasdrapeau par SiegeX fonctionne; Cependant, je suis sur Zsh. Quelque chose de semblable existe-t-il?

Adrian Petrescu
la source
dans zsh, si vous voulez savoir d' où ça vimvient , vous pouvez utiliserwhere vim
Matija Nalis

Réponses:

105

whichest en fait une mauvaise façon de faire des choses comme ça, car cela permet de deviner votre environnement en fonction $SHELLdes fichiers de démarrage (il pense) que le shell utilise; non seulement cela donne-t-il parfois tort, mais on ne peut généralement pas lui dire de se comporter différemment. ( whichsur mon Ubuntu 10.10 ne comprend pas, --skip-aliascomme mentionné par @SiegeX, par exemple.) typeutilise l’environnement shell actuel au lieu de fouiller dans vos fichiers de configuration, et on peut lui dire d’ignorer des parties de cet environnement, ce qui vous montre ce qui se passera réellement. arriver au lieu de ce qui se passerait dans une reconstruction de votre shell par défaut.

Dans ce cas, type -Pignorera tous les alias ou fonctions:

$ type -P vim
/usr/bin/vim

Vous pouvez également lui demander de retirer toutes les couches, une à la fois, et de vous montrer ce qu'il trouverait:

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

(En développant ceci à partir des commentaires :)

Le problème, whichc'est qu'il s'agit généralement d'un programme externe au lieu d'un shell intégré, ce qui signifie qu'il ne peut pas voir vos alias ni vos fonctions et doit essayer de les reconstruire à partir des fichiers de démarrage / configuration du shell. (Si c'est un shell intégré, comme c'est le cas, zshmais apparemment pas bash, il est plus susceptible d'utiliser l'environnement du shell et de faire la bonne chose.)

typeest une commande compatible POSIX qui doit se comporter comme si elle était intégrée (c’est-à-dire qu’elle doit utiliser l’environnement du shell dans lequel elle est invoquée, y compris les alias et les fonctions locaux); elle est donc généralement intégrée.

Il ne se trouve généralement pas dans csh/ tcsh, bien que, dans la plupart des versions modernes, il s’agisse d’ whichun shell intégré qui fait le bon choix; parfois intégré est au whatlieu, et parfois il n'y a pas de bonne façon de voir l'environnement de l'interpréteur de commandes actuel de csh/ tcshdu tout.

geekosaur
la source
6
Merci! C'est quelque chose de très utile à ajouter à mon sac à malices. J'aime particulièrement que type -asemble renvoyer toutes les instances sur votre $PATH, pas seulement le premier. Je pense que je vais alias whichto type:)
Adrian Petrescu Le
2
@ geekosaur: Merci. Si typefait partie de la norme POSIX, c’est la voie à suivre. Pour répondre à ma question, tapez works sur zsh également (sur Debian). Pourquoi les distributions ne se débarrassent -elles pas whatet whichsi elles ne sont pas normalisées et ne disposent pas de fonctionnalités supplémentaires?
Faheem Mitha le
1
Non, même pas à distance.
geekosaur
1
@Faheem: en ce qui concerne la documentation, je commencerais par info bash 'Bash builtins'Linux, bien que vous puissiez également l’obtenir à partir du zshmanuel de référence. Plus officiellement, pubs.opengroup.org/onlinepubs/009695399/utilities/type.html (que je remarque ne spécifie pas réellement -Pou -a, ou même -pqui était la forme originale de -P, mais exige qu'il utilise l'environnement shell actuel).
geekosaur
2
type -pse comporte différemment entre zsh et bash. type -Pn'existe pas du tout dans zsh.
kojiro
15

Dans bash:

type -P vim

Dans zsh:

type -p vim

À la fois:

/usr/bin/which vim

Ou:

( unalias vim; type vim )
Mikel
la source
2
Le dernier est cool. Nous pouvons avoir un alias pour le faire. :)
balki
En fait, je dois utiliser le type -P, et non lequel, si je veux la bonne réponse. Aucun alias ou fonction n'est concerné.
Dr Eval, lequel "lequel"? Quel chapeau rouge?
Mikel
@ Mikel RH7.4. GNU qui v2.20.
4

En zsh whichest intégré car cette commande indique:

$ whence -w which
which: builtin

Pour exécuter la commande externe (dans n’importe quel shell) which, utilisez le chemin complet :

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

la commande lsa donc été trouvée (une valeur de sortie de 0) et se trouve à /bin/ls.

À l'intérieur zsh; Un moyen (à côté de celui ci-dessus) de rechercher des commandes externes est:

$ whence -p ls
/bin/ls

Cependant, cela ne résoudra pas les alias imbriqués tels que:

$ alias dire='ls -l'

La commande signalera qu'aucune direcommande n'a été trouvée.

$ whence -p dire; echo $?
1

Pour résoudre les alias imbriqués (manuellement), voir Resolve nested aliases to their source commands

HalosGhost
la source
2

Mine définie comme telle

alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
Meitham
la source
1

Essayez ce qui suit:

which --skip-alias vim
SiegeX
la source
1
Intéressant! Cela fonctionne sur Bash, mais pas sur Zsh (je ne pensais vraiment pas que cela dépendrait du shell). Cela m'a fait comprendre qu'il s'agissait en whichfait d'un shell intégré et non d'un utilitaire Unix standard, comme je l'avais supposé. Je devrais donc modifier ma question et spécifier Zsh. Merci de me l'avoir signalé!
Adrian Petrescu
whichn'est pas intégré, du moins pas sur Debian. C'est un script shell, et une partie de debianutils, fonctionne donc sur zsh. Cependant, --skip-aliasn’est pas une option whichsur Debian. Existe-t-il différentes variétés de whichflottants? Cela ne semble pas être une commande normalisée.
Faheem Mitha le
@Faheem Mitha: C'est un zsh intégré. Voir man zshbuiltins. quel nom [-wpams] ... Équivalent à whence -c.
Mikel
Ouais sur Xubuntu bash, ce n'est pas intégré et n'a pas l' --skip-aliasoption.
polym
Sur CentOS (et RHEL?) 6, il s’agit d’un exécutable /usr/bin/whichet d’un alias /etc/profile.dqui lui permet de gérer les alias mais --skip-aliasfonctionne. En conséquence, which whichaffiche l'alias, mais command which whichaffiche l'exécutable!
dave_thompson_085
0

Une autre alternative est command which vim, qui fonctionne de la même manière à la fois zshetbash

Par exemple sur mon mac:

LOLcalhost :: ~ % command which grep
/usr/local/bin/grep
Zee Alexander
la source
Ah assez bien.
Zee Alexander
0

Les deux typeet whichse comportent différemment selon votre type de shell.

Dans bash, whichest une commande existe dans PATH. Il recherche la commande que vous fournissez PATH. Bash builtin type -P(P pour PATH) se comporte exactement comme which.

Dans ZSH, les deux whichet typesont des fonctions intégrées et des fonctions partielles de la fonction intégrée whence. which -pc'est ce que tu veux. Cela force une recherche de chemin. (l' -Poption n'est pas disponible pour typeZSH.)

d'où [-vcwfpamsS] [-x num] nom ...

-p

Effectuez une recherche de chemin pour name, même s'il s'agit d'un alias, d'un mot réservé, d'une fonction shell ou d'un paramètre intégré.

Plus de manuel de ZSH.

quel nom [-wpamsS] [-x num] ...

Équivalent à d'où -c.

Pour ignorer builtin whichet forcer l'utilisation de la commande whichde PATHZSH:

alias which="command which"
Simba
la source