Linux / Commande command : contourner une fonction et vérifier un nom
command nom exécute une commande en omettant la recherche des fonctions de même nom ; dans Bash, le résultat peut être une commande interne ou un programme externe. Utilisez command -v nom pour consulter la résolution sans exécuter le nom recherché, et command -V nom pour obtenir une explication plus détaillée.
Distinguer exécution et consultation
command est une commande intégrée au shell, définie aussi par POSIX, la famille de normes qui décrit des interfaces de systèmes de type Unix. Les exemples pratiques de cet article utilisent Bash ; les messages et certains détails peuvent différer dans un autre interpréteur.
La notation générale ci-dessous n’est pas une commande à recopier telle quelle :
command [-p] nom [arguments ...]
command [-p] -v nom
command [-p] -V nom
Sans -v ni -V, la cible est exécutée :
command printf '%s\n' 'Bonjour'
command ls -d .
La première commande peut utiliser le printf interne de Bash. La seconde demande une liste limitée au répertoire courant lui-même. Le préfixe n’impose donc pas un fichier externe et ne change pas les options du programme appelé.
| Forme | Action |
|---|---|
command nom arguments |
Exécuter sans rechercher une fonction portant ce nom. |
command -v nom |
Afficher une indication concise de résolution, sans exécuter la cible. |
command -V nom |
Afficher une description destinée à la lecture humaine. |
command -p nom |
Utiliser le chemin de recherche par défaut du shell pour les utilitaires standard. |
La spécification POSIX de command distingue explicitement la consultation de la résolution et l’exécution. La référence des commandes internes Bash décrit l’implémentation utilisée ici.
Éviter une récursion dans une fonction enveloppe
Une fonction peut porter le nom d’un programme ou d’un builtin afin d’ajouter un traitement. Si son corps rappelle simplement le même nom, il risque de rappeler la fonction au lieu de l’outil souhaité.
L’exercice complet suivant crée une fonction printf temporaire dans un sous-shell. Il retire seulement dans ce sous-shell un éventuel alias de ce nom, puis affiche un message de suivi sur la sortie d’erreur avant d’appeler le builtin :
(
builtin unalias printf 2>/dev/null || :
function printf {
builtin printf '%s\n' 'Appel de la fonction printf' >&2
command printf "$@"
}
\printf '<%s>\n' 'un argument avec espaces' '*'
)
La sortie standard attendue conserve l’espace et l’astérisque comme données :
<un argument avec espaces>
<*>
Le message Appel de la fonction printf apparaît séparément sur la sortie d’erreur. Dans la fonction, command printf omet la fonction et atteint ici le builtin. Écrire un simple appel de printf à cet endroit pourrait provoquer une récursion.
"$@" transmet les arguments en conservant leur séparation d’origine. Une forme non citée peut découper un argument contenant des espaces et développer un joker comme *. Les parenthèses limitent la fonction et la suppression d’alias à l’exercice ; votre session retrouve ses définitions à la sortie.
Pour imposer spécifiquement le builtin dans Bash, utilisez builtin printf. Pour autoriser le builtin ou un fichier selon la recherche du shell, command printf convient. Si vous exigez un programme externe, inspectez les fichiers avec type -P printf et vérifiez le candidat au lieu de supposer que command l’impose.
Interpréter correctement command -v et command -V
Un résultat n’est pas nécessairement un chemin
command -v cd
command -v printf
command -v git
command -V printf
La réponse peut décrire une commande interne, une fonction, un alias, un mot réservé ou un fichier. Ne placez donc pas systématiquement le résultat de command -v dans un test de fichier. Une chaîne telle que printf peut désigner le builtin, même si un fichier de ce nom existe dans le répertoire courant.
-V est utile pour comprendre une réponse ambiguë, mais son format n’est pas destiné à une analyse automatique stable. Pour lister les candidats et obtenir une catégorie explicite dans Bash, consultez le guide de type, -a, -t et -P.
La consultation peut trouver une fonction que l’exécution omet
Cette différence est facile à manquer : command -v nom renseigne sur la résolution du nom, alors que command nom omet les fonctions. Essayez ce bloc dans un environnement où aucun exécutable jb_command_demo n’est présent :
(
function jb_command_demo {
builtin printf '%s\n' 'Corps de la fonction'
}
command -v jb_command_demo
command jb_command_demo
builtin printf 'Code de l’exécution : %s\n' "$?"
)
La consultation affiche le nom de la fonction et réussit. L’exécution ne lance pas son corps ; faute de builtin ou de programme correspondant, elle échoue avec le code 127, puis la dernière ligne affiche ce code. Les diagnostics exacts peuvent varier avec la langue et le shell.
Ce test ne crée aucun fichier et la fonction disparaît à la fin du sous-shell. Il montre pourquoi un test de résolution réussi ne suffit pas à garantir qu’un appel ultérieur avec un autre mode de recherche lancera la même chose.
Comprendre les alias et les limites du préfixe
Dans une écriture ordinaire comme command ls, ls n’occupe pas la position du mot de commande initial et son alias n’est normalement pas développé. La recherche de fonction est ensuite omise par command. Ces deux mécanismes interviennent à des moments différents.
L’expansion des alias a lieu lors de la lecture du code. command peut lui-même être un alias, et un alias dont la valeur finit par un espace peut provoquer l’examen du mot suivant comme candidat à l’expansion. Ne considérez donc pas le préfixe comme une opération universelle de citation du texte.
type -a command
type -a ls
command -V ls
Une barre oblique inverse devant un nom, comme \ls, évite l’expansion de son alias mais laisse possible la recherche d’une fonction. Un chemin explicite vers un fichier choisi évite ces résolutions par nom ; son emplacement doit être confirmé sur le système concerné.
command ne transforme pas non plus une ligne entière en texte littéral. Dans une expression contenant un tube, un point-virgule ou une redirection, le shell continue à analyser ces opérateurs normalement. Le préfixe s’applique à la commande qu’il introduit, pas automatiquement aux autres commandes de la ligne.
Utiliser le chemin par défaut avec -p
-p demande un chemin de recherche par défaut permettant de trouver les utilitaires standard. Il peut aider lorsque le PATH courant a été personnalisé ou ne permet plus de trouver une commande standard :
command -p ls -d .
command -p getconf PATH
La seconde forme interroge le chemin standard au moyen de getconf, lorsqu’il est fourni dans l’environnement concerné. La valeur précise dépend du système ; ne recopiez pas celle d’une autre machine comme une constante universelle.
-p ne modifie pas durablement votre variable PATH et n’impose pas une version ou un fournisseur de programme. Il ne remplace pas la vérification des chemins et permissions dans un environnement contrôlé. Les programmes lancés peuvent eux-mêmes rechercher d’autres commandes selon leur environnement.
Écrire un test de résolution sans analyser les messages
Pour informer l’utilisateur qu’un nom est connu du shell, utilisez le statut de command -v, en redirigeant ses deux sorties si vous ne voulez pas afficher de détails. Le script complet suivant ne lance pas le nom recherché.
Enregistrez-le dans un nouveau fichier tester-resolution.sh :
#!/usr/bin/env bash
if [ "$#" -ne 1 ] || [ -z "$1" ]; then
printf 'Utilisation : bash tester-resolution.sh nom\n' >&2
exit 64
fi
if command -v -- "$1" >/dev/null 2>&1; then
printf 'Nom résolu dans ce shell : %s\n' "$1"
else
printf 'Nom introuvable dans ce shell : %s\n' "$1" >&2
exit 1
fi
Puis exécutez-le avec Bash :
bash tester-resolution.sh printf
bash tester-resolution.sh __nom_absent_pour_essai__
printf 'Dernier code de retour : %s\n' "$?"
Le premier appel réussit normalement. Si le second nom n’existe pas, il affiche un diagnostic et termine avec 1. Le script choisit 64 pour un nombre incorrect d’arguments ou un nom vide. -- protège un nom commençant par un tiret contre son interprétation comme option par Bash.
Ce script examine son propre environnement d’exécution. Un Bash séparé ne reprend pas automatiquement les alias et toutes les fonctions du terminal parent ; effectuez directement le test dans ce terminal pour en inspecter l’état. Une résolution réussie ne vérifie ni une option précise, ni la version, ni les permissions nécessaires à l’opération future.
Si l’objectif exige un fichier externe, utilisez les outils appropriés de recherche de fichiers plutôt qu’un test tel que [ -f "$(command -v nom)" ], qui peut confondre un nom de builtin avec un fichier local. Même un chemin valide au moment du contrôle peut changer ensuite : le test ne fige pas le fichier pour une exécution ultérieure.
Lire les codes de retour et choisir le bon outil
En mode d’exécution, command transmet le statut de la cible. Un échec de la cible ne signifie donc pas que le préfixe lui-même est défectueux :
command false
printf 'Code de false : %s\n' "$?"
command __nom_absent_pour_essai__
printf 'Code du nom absent : %s\n' "$?"
Dans cet exemple, false termine avec 1 et un nom réellement introuvable avec 127. Le code 126 correspond au cas où la cible est trouvée mais ne peut pas être invoquée. Des erreurs de command peuvent aussi produire 127 ; ne déduisez pas tout le diagnostic du seul nombre.
Avec -v et -V, un statut nul indique une consultation réussie et un statut non nul une absence de nom ou une erreur. Il ne s’agit pas du statut d’un programme qui aurait été exécuté.
| Outil | Rôle principal |
|---|---|
command nom |
Exécuter en omettant la recherche de fonction ; un builtin peut encore être choisi. |
builtin nom |
Appeler explicitement une commande interne Bash. |
exec programme |
Remplacer le processus du shell par un programme ; en cas de succès, l’ancien shell ne reprend pas. |
env VAR=valeur programme |
Lancer un programme avec un environnement ajusté, sans accéder directement aux fonctions et builtins du shell parent. |
type nom |
Décrire la résolution sans exécuter le nom. |
Comme command est intégré au shell, une forme telle que sudo command … ne garantit pas qu’un exécutable de ce nom existe. Pour une opération administrative, passez normalement le programme externe nécessaire à sudo ; ne lancez un shell supplémentaire que si sa syntaxe est réellement requise. Pour relire les détails du builtin dans votre Bash, utilisez help command.




