Comment vérifier qu'une commande existe en Bash ? Comment vérifier la disponibilité des prérequis d'un script ?
Une méthode permettant de vérifier qu’une commande existe consiste à tester le retour de « command -v <commande_a_tester> » :
fhh@mafalda ~ $ command -v ls alias ls='ls --color=auto' fhh@mafalda ~ $ echo $? 0 fhh@mafalda ~ $ command -v ls > /dev/null && echo "ls existe" ls existe |
Si la commande existe et est accessible via le PATH ou au chemin spécifié, « command -v » retourne « 0 », sinon, le retour est supérieur à « 0 » :
fhh@mafalda ~ $ command -v youhou # youhou n'existe pas dans le PATH ou comme commande interne : fhh@mafalda ~ $ echo $? 1 fhh@mafalda ~ $ command -v ../../usr/bin/date # date est accessible au chemin spécifié : fhh@mafalda ~ $ echo $? 0 |
Vérifier les prérequis d’un script
Dans un script une manière de tester les prérequis (programmes nécessaires à l’exécution du code) consiste à placer la liste des dépendances dans une variable et à tester leur disponibilité. Ce qui peut donner une fonction du genre de « checkrequirements » :
#!/bin/bash _needed_commands="ls ps dhclient /sbin/dhclient ./montest.sh /bin/bash truc machin" ; checkrequirements () { command -v command >/dev/null 2>&1 || { echo "WARNING> \"command\" not found. Check requirements skipped !" return 1 ; } for requirement in ${_needed_commands} ; do echo -n "checking for \"$requirement\" ... " ; command -v ${requirement} > /dev/null && { echo "ok" ; continue ; } || { echo "required but not found !" ; _return=1 ; } done [ -z "${_return}" ] || { echo "ERR > Requirement missing." >&2 ; exit 1 ; } } checkrequirements |
qui donne à l’exécution :
1 2 3 4 5 6 7 8 9 10 11 12 | fhh@mafalda ~ $ ./montest.sh checking for "ls" ... ok checking for "ps" ... ok checking for "dhclient" ... required but not found ! checking for "/sbin/dhclient" ... ok checking for "./montest.sh" ... ok checking for "/bin/bash" ... ok checking for "truc" ... required but not found ! checking for "machin" ... required but not found ! ERR > Requirement missing. fhh@mafalda ~ $ echo $PATH /usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games |
Note : Ligne 4, « dhclient » est marqué comme non trouvé car il n’est pas dans les répertoires du PATH de l’utilisateur. En revanche, en spécifiant le chemin complet vers le binaire (en absolu), ligne 5, la dépendance est trouvée. Ligne 6, on voit que les chemins peuvent être spécifié en relatif.
Plus d’infos sur « command »
L’option « -v », en minuscule, affiche :
- la commande seule s’il s’agit d’une commande interne ;
- le chemin absolu vers la commande si elle est dans le PATH ou relatif si elle à été précisée en relatif ;
- la définition de l’alias s’il s’agit d’un alias ;
- …
fhh@aaricia ~ $ command -v test test fhh@aaricia ~ $ command -v date /usr/bin/date fhh@aaricia ~ $ command -v ../../usr/bin/date ../../usr/bin/date fhh@aaricia ~ $ command -v ls alias ls='ls --color=auto' fhh@aaricia ~ $ yop () { echo "Fonction yop" ;} fhh@aaricia ~ $ command -v yop yop |
L’option « -V », en majuscule, affiche les mêmes informations que son homologue minuscule mais dans un format accès « lisibilité utilisateur » :
fhh@aaricia ~ $ command -V test test is a shell builtin fhh@aaricia ~ $ command -V date date is /usr/bin/date fhh@aaricia ~ $ command -V ../../usr/bin/date ../../usr/bin/date is ../../usr/bin/date fhh@aaricia ~ $ command -V ls ls is aliased to `ls --color=auto' fhh@aaricia ~ $ yop () { echo "Fonction yop" ;} yop is a function yop () { echo "Fonction yop" } |
Notez le comportement de l’option sur une fonction …
L’option « -p » execute la commande « originale » c’est à dire directement depuis le PATH :
fhh@aaricia ~ $ alias date="date +%s" fhh@aaricia ~ $ date 1378889936 fhh@aaricia ~ $ command -p date Wed Sep 11 10:59:20 CEST 2013 |
Dans cet exemple, l’option « -p » permet d’utiliser « date » directement et non l’alias défini pour cette commande.
Note : dans cet exemple, « command -p date » équivaut à « \date ».
[…]
PS: J’ignore si mon précédent commentaire est passé avec mes cookies désactivés. Voilà pourquoi je reposte une 2nde fois.
C’est passé 😉 Merci pour ce retour. En effet, l’exemple concerne « bash ». De manière générale, « bash » est quasi aussi rependu qu' »sh » ce qui n’est pas le cas de « ksh »… Pour ma part, je reste donc basique sans me priver de confort donc « bash » plutôt que « ksh » et qu' »sh ». Mais c’est purement personnel.
Bonsoir,
Lorsque je programme en POSIX sh, qui ne comporte pas ‘command’, j’ai tendance à tester la présence de l’exécutable dans /usr/bin, avec test.
Quelque chose du genre:
[ -x "/usr/bin/date" ] && printf "%s\n" "date is installed"
Même si parfois les exécutables sont dans /sbin ou dans /usr/local/bin, je trouve cette manère très efficace.
Avec ksh, j’utilise whence + test comme ceci:
[ -n "$(whence date)" ] && print "date is installed"
Cordialement