commande which
La commande which affiche le chemin complet des commandes (shell).
Syntaxe
1 | $ which [option] -- programname [...] |
Description
La commande which peut prendre un ou plusieurs arguments. Pour chacun d’entre eux elle affiche sur la sortie standard (stdout) le chemin complet des exécutables qui auraient pu être saisis directement depuis le prompt Shell. La commande which recherche l’exécutable dans les différents répertoires listés dans la variable d’environnement PATH (et utilise le même algorithme que BASH).
Options
--all, -a Affiche tous les chemins correspondants trouvés dans PATH, et pas seulement le premier. C.f. exemple 3
--read-alias, -i Permet de lire les alias depuis l’entrée standard (stdin), et rapporte les correspondances trouvées sur la sortie standard. Ceci est utile en combinaison avec un alias sur which lui-même. Par exemple alias which='alias | which -i'. C.f. Exemple 4
--skip-alias Permet d’ignorer l’option --read-alias si cette dernière est présente. C’est utile pour rechercher explicitement un exécutable normal alors que l’option --read-alias est déclarée. C.f. Exemple 5
--read-functions Lit les définitions des fonctions depuis l’entrée standard, et rapporte les correspondances trouvées sur la sortie standard. Ceci est utile s’il est combiné à une fonction intégrant which lui-même. Par exemple :
which() { declare -f | which --read-functions $@ }
export -f which
C.f. Exemple 6
--skip-functions Permet d’ignorer l’option --read-functions si cette dernière est présente. C’est utile pour rechercher un exécutable normal alors que l’option --read-functions est déclarée.
--skip-dot Ignore les répertoires listés dans PATH commençant par un point (caractère ‘.’ ). C.f. Exemple 7
--skip-tilde Ignore les répertoires dans PATH qui commence par le symbole tilde (~) ainsi que les exécutables qui se trouvent dans le répertoire HOME. C.f. Exemple 8
--show-dot Si un répertoire dans PATH commence avec un point (.) et si l’exécutable correspond à ce répertoire, alors afficher "./nom_exécutable" plutôt que le chemin complet. C.f. Exemple 9
--show-tilde Afficher un tilde (symbole ~) quand un répertoire correspond à HOME. Cette option est ignorée lorsqu’elle est invoquée en tant que root.
--tty-only Stop le traitement des options qui se trouvent sur la droite si on est pas sur un tty.
--version, -v, -V Affiche des informations concernant la version sur la sortie standard.
--help Affiche une aide basique d’utilisation (aide mémoire) sur la sortie standard.
Valeurs retournées
Si jamais vous utilisez la commande which à l’interieur d’un script Shell vous auriez peut-être besoin de connaître quelles sont les valeurs retournées par which.
Les valeurs retournées sont :
0 si toutes les commandes sont trouvées;
1 si une ou plusieurs commandes ne sont pas trouvées;
2 s’il y a une option non reconnue.
Exemples
Exemple 1 – Afficher le chemin d’une commande
L’exemple ci-dessous, montre comment utiliser la commande which pour connaître l’emplacement de la commande ls.
1 2 | $ which ls /bin/ls |
Ci-dessus, on peut voir dans notre exemple que le résultat de la commande which nous indique que l’exécutable ls se trouve dans le répertoire /bin.
Exemple 2 – Afficher le chemin de plusieurs exécutables
Pour afficher le chemin de plusieurs exécutables, il suffit de fournir la liste des exécutables en paramètre. Dans l’exemple suivant, on fournit trois exécutables connus (ls, du et mv) en paramètre à which.
1 2 3 4 | $ which ls du mv /bin/ls /usr/bin/du /bin/mv |
Comme on peut l’observer dans le résultat de l’exemple ci-dessus, which nous fourni le chemin complet de chacun des exécutables passés en paramètres.
Exemple 3 – Afficher tous les chemins existants
S’il existe plusieurs chemins pour un exécutable, par défaut which affiche seulement le premier chemin trouvé. Nous allons voir au travers de cette exemple, comment afficher à l’aide de l’option -a tous les chemins existants.
3.a. Copions l’exécutable ls
Ci-dessous, nous commençons par ajouter le répertoire /home/romain/bin à la variable d’environnement PATH. Puis nous copions l’exécutable ls dans /home/romain/bin/.
1 2 | $ PATH=$PATH:/home/romain/bin $ cp /usr/bin/ls /home/romain/bin/ |
Nous avons maintenant deux exécutables ls se trouvant chacun dans des répertoires déclarés dans la variable d’environnement PATH.
3.b. Utilisons which pour trouver l’exécutable ls
Dans l’exemple, ci-dessous, nous pouvons voir que which nous affiche qu’un seul répertoire malgré que la commande ls se trouve dans deux répertoires déclarés dans la variable d’environnement PATH.
1 2 | $ which ls /usr/bin/ls |
Pour afficher tous les répertoires (déclarés dans PATH) d’un exécutable il est nécessaire d’utiliser l’option -a, --all . Comme on peut le voir dans l’exemple ci-dessous, avec l’option -a which affiche tous les répertoires dans lesquels se trouve l’exécutable ls. which affiche le répertoire d’origine /home/bin de l’exécutable ls et le répertoire dans lequel nous l’avons copié /home/romain.
1 2 3 | $ which -a ls /usr/bin/ls /home/romain/bin/ls |
Exemple 4 – Lecture des alias
Les alias peuvent rendre les résultats de which déroutants. Voici au travers d’un exemple une situation démontrant ce problème et comment la solutionner en utilisant l’option -i de which afin d’indiquer à ce dernier de prendre en considération les alias.
J’utilise ci-dessous la commande now qui me permet de savoir qu’elle heure est-il (Ne cherchez pas, elle n’existe sans doute pas sur votre système).
1 2 | $ now 22:16:16 |
Je souhaiterais savoir où se trouve l’exécutable now, alors je tente d’utiliser la commande which, comme ci-dessous :
1 2 | $ which now which: no now in (/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl:/home/romain/bin) |
Malheureusement, comme on peut l’observer ci-dessus, which m’indique que l’exécutable now est introuvable dans les répertoires déclarés dans la variable d’environnement PATH. Pourquoi cette commande now fonctionne dans mon terminal si which me dit qu’il ne la trouve pas.
Voici la réponse :
1 2 | $ alias alias now='date +"%T"' |
En tapant la commande alias, je m’aperçois qu’en réalité la commande now n’est pas un exécutable mais un alias sur la commande date suivi de paramètres très spécifiques.
L’option --read-alias, -i indique à which de prendre en compte les alias, à condition de combiner cette dernière en créant un alias de which lui-même. Ajoutons donc, cette alias sur which à notre fichier /etc/profile, comme ci-dessous :
1 2 3 4 5 6 7 8 | # Je passe en root $ su - # Je lance mon éditeur préféré # vi /etc/profile # j'ajoute la ligne suivante à /etc/profile et j'enregistre alias which='alias | which -i' |
Maintenant que l’alias sur which lui-même est ajouté à mon fichier /etc/profile, je quitte root (via la commande exit), je recharge mon fichier profile depuis l’utilisateur courant, comme ci-dessous :
1 | . /etc/profile |
Maintenant, essayons de demander à which s’il connait la commande now :
1 2 3 | $ which now alias now='date +"%T"' /usr/bin/date |
Comme vous pouvez le voir, maintenant which reconnait la commande now et nous indique que c’est un alias sur l’exécutable date qui se trouve dans /usr/bin.
Exemple 5 – Ignorer les alias
Maintenant que nous avons ajouter dans notre fichier /etc/profile la déclaration de l’alias alias which='alias | which -i' which va vérifier dans les alias la présence ou non de la commande que nous lui fournissons en paramètre.
Ci-dessous, on demande à which, où se trouve l’exécutable ‘now’. Ce dernier nous répond que c’est un alias sur l’exécutable date.
1 2 3 | $ which now alias now='date +"%T"' /usr/bin/date |
Si vous ne souhaitez pas que which prenne en considération les alias, alors vous pouvez utiliser l’option --skip-alias comme ci-dessous :
1 2 | $ which --skip-alias now which: no now in (/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl) |
Comme vous pouvez, le constater ci-dessus, which, ne reconnait plus l’alias ‘now’.
Exemple 6 – Lecture des fonctions
Admettons que vous ayez une commande qui vous permette de faire des additions telle que celle représentée ci-dessous :
1 2 | $ addition 1 1 2 |
Si l’on demande (ci-dessous) à which de nous indiquer le chemin de cet exécutable il ne le trouve pas :
1 2 | $ which addition which: no addition in (/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl) |
Ceci vient du fait que la commande addition est une fonction, nous pouvons le vérifier en listant les fonctions comme ci-dessous :
1 2 3 4 5 | $ declare -f addition () { expr $1 + $2 } |
On constate ci-dessus que la fonction addition utilise expr pour faire l’opération.
Afin que which prenne en compte les fonctions déclarées dans le système il est indiqué dans le man d’utiliser l’option --read-functions . Malheureusement, cela a pour conséquence d’appeler which de manière récursive (en boucle) et d’utiliser tout l’espace mémoire disponible du système. Je ne sais donc pas comment utiliser cette option…
Exemple 7 – Ignorer les répertoires qui commence par un « . »
L’option --skip-dot de which permet d’ignorer les répertoire commençant par un point (.) listés dans la variable d’environnement PATH.
Examinons notre variable d’environnement :
1 2 | $ echo $PATH /usr/local/sbin:/usr/local/bin:/usr/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl |
Comme on peut le voir ci-dessus, aucun répertoire listé ne commence par un point.
Ajoutons un répertoire commençant par un point (.) à notre variable PATH :
1 | $ PATH=$PATH:./bin |
Vérifions que notre répertoire « ./bin » a bien été ajouté à la variable PATH :
1 2 | $ echo $PATH /usr/local/sbin:/usr/local/bin:/usr/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl:./bin |
Créons maintenant un petit programme très simple (script exécutable) qui affiche « bonjour » et qui se trouve dans ./bin :
1 2 | $ echo "printf bonjour\\\n" > bin/monProgramme $ chmod +x bin/monProgramme |
Exécutons notre petit programme afin de vérifier s’il marche correctement :
1 2 | $ bin/monProgramme bonjour |
Demandons à which le chemin de notre exécutable :
1 2 | $ which monProgramme /home/romain/bin/monProgramme |
Comme on peut l’observer ci-dessus, which nous affiche le chemin complet du programme que nous venons de créer.
Nous y sommes, testons l’option --skip-dot de which :
1 2 | $ which --skip-dot monProgramme which: no monProgramme in (/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl:./bin) |
Comme nous pouvons le constater ci-dessus, avec l’option --skip-dot , which n’est pas allé chercher dans ./bin (pourtant renseigné dans la variable PATH).
Exemple 8 – Ignorer les répertoires qui commence par un « ~ »
L’option --skip-tilde permet d’ignorer les répertoires dans PATH qui commence par le symbole tilde (~) ainsi que les exécutables qui se trouvent dans le répertoire HOME.
Considérons que nous avons un exécutable nommé monProgramme et qui se trouve dans notre répertoire HOME qui est « /home/romain ».
1 2 3 4 5 6 | $ pwd /home/romain $ ls bin Desktop monProgramme |
Demandons à which s’il connait l’exécutable :
1 2 | $ which monProgramme which: no monProgramme in (/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl) |
Which nous informe que la commande est introuvable. Ceci est normal, car cette dernière se trouve dans le répertoire HOME et que ce dernier n’est pas déclaré dans la variable d’environnement PATH. Ajoutons donc, comme ci-dessous le répertoire HOME à la variable PATH.
1 | $ PATH=$PATH:~ |
Interrogeons encore une fois which afin de savoir si maintenant il connaît la commande :
1 2 | $ which monProgramme /home/romain/monProgramme |
Comme on peut le voir ci-dessus, which trouve bien la commande dans notre répertoire HOME.
Essayons l’option --skip-tilde :
1 2 | $ which --skip-tilde monProgramme which: no monProgramme in (/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl:/home/romain) |
Vous pouvez voir ci-dessus que lorsque l’option --skip-tilde est invokée which ne cherche plus dans notre répertoire HOME.
Exemple 9 – Afficher les répertoires qui commence par un « . » tel quel
Considérons que nous avons le répertoire « ./bin » dans notre variable d’environnement PATH. Et considérons que ce répertoire contient un exécutable nommé monProgramme.
Si nous interrogeons which sur l’emplacement de la commande monProgramme, which nous indique son chemin complet :
1 2 | $ which monProgramme /home/romain/bin/monProgramme |
En utilisant l’option --show-dot which nous affiche le répertoire tel qu’il est définit dans PATH (commençant avec un . ) :
1 2 | $ which --show-dot monProgramme ./bin/monProgramme |