Comment vérifier si la commande existe dans un script shell?
j'écris mon premier script shell. Dans mon script je voudrais vérifier si une commande existe, et si pas le cas, installez l'exécutable. Comment puis-je vérifier si cette commande existe?
if #check that foobar command doesnt exist
then
#now install foobar
fi
8 réponses
en général, cela dépend de votre shell, mais si vous utilisez bash, zsh, ksh ou sh (tel que fourni par dash), ce qui suit devrait fonctionner:
if ! type "$foobar_command_name" > /dev/null; then
# install foobar here
fi
pour un vrai script d'installation, vous voudriez probablement être sûr que type
ne retourne pas avec succès dans le cas où il y a un alias foobar
. À bash vous pourriez faire quelque chose comme ceci:
if ! foobar_loc="$(type -p "$foobar_command_name")" || [[ -z $foobar_loc ]]; then
# install foobar here
fi
essayez d'utiliser type
:
type foobar
par exemple:
$ type ls
ls is aliased to `ls --color=auto'
$ type foobar
-bash: type: foobar: not found
C'est préférable à which
pour quelques raisons:
1) les implémentations par défaut which
ne prennent en charge que l'option -a
qui affiche toutes les options, vous devez donc trouver une version alternative pour prendre en charge les alias
2) type vous dira exactement ce que vous regardez (que ce soit une fonction bash ou un alias ou un bon binaire).
3) le type n'a pas besoin d'un sous-processus
4) le type ne peut pas être masqué par un binaire (par exemple, sur une machine linux, si vous créez un programme appelé which
qui apparaît dans path avant le vrai which
, les choses frappent le ventilateur. type
, d'un autre côté, est un shell intégré [Oui, un subordonné l'a fait par inadvertance une fois]
vérifiez si un programme existe à partir d'un script Bash couvre très bien cela. Dans n'importe quel script shell, il est préférable d'exécuter command -v $command_name
pour tester si $command_name
peut être exécuté. Dans bash, vous pouvez utiliser hash $command_name
, qui hache aussi le résultat de n'importe quelle recherche de chemin, ou type -P $binary_name
si vous voulez seulement voir des binaires (pas de fonctions etc.)
cinq voies, 4 pour bash et 1 addition pour zsh:
-
type foobar &> /dev/null
-
hash foobar &> /dev/null
-
command -v foobar &> /dev/null
-
which foobar &> /dev/null
-
(( $+commands[foobar] ))
(zsh seulement)
vous pouvez mettre n'importe lequel d'entre eux à votre if
clause. D'après mes tests ( https://www.topbug.net/blog/2016/10/11/speed-test-check-the-existence-of-a-command-in-bash-and-zsh / ), la 1ère et la 3ème méthode sont recommandées en bash et la 5ème méthode est recommandée en zsh en termes de vitesse.
la question ne spécifie pas de coquille, donc pour ceux qui utilisent fish (friendly interactive shell):
if command --search foo >/dev/null do
echo exists
else
echo does not exist
end
pour la compatibilité POSIX de base, utilisez le drapeau -v
qui est un alias pour --search
ou -s
.
which <cmd>
voir aussi options which
supports pour les alias si applicable à votre cas.
exemple
$ which foobar
which: no foobar in (/usr/local/bin:/usr/bin:/cygdrive/c/Program Files (x86)/PC Connectivity Solution:/cygdrive/c/Windows/system32/System32/WindowsPowerShell/v1.0:/cygdrive/d/Program Files (x86)/Graphviz 2.28/bin:/cygdrive/d/Program Files (x86)/GNU/GnuPG
$ if [ $? -eq 0 ]; then echo "foobar is found in PATH"; else echo "foobar is NOT found in PATH, of course it does not mean it is not installed."; fi
foobar is NOT found in PATH, of course it does not mean it is not installed.
$
PS: notez que tout ce qui est installé ne peut pas être dans PATH. Habituellement pour vérifier si quelque chose est" installé " ou pas, on utilise des commandes d'installation pertinentes au système D'exploitation. Par exemple: rpm -qa | grep -i "foobar"
pour RHEL.
une fonction que j'ai dans un script d'installation fait pour exactement cela
function assertInstalled() {
for var in "$@"; do
if ! which $var &> /dev/null; then
echo "Install $var!"
exit 1
fi
done
}
exemple d'appel:
assertInstalled zsh vim wget python pip git cmake fc-cache
Une fonction qui fonctionne dans les deux bash et zsh:
# Return the first pathname in $PATH for name in
function cmd_path () {
if [[ $ZSH_VERSION ]]; then
whence -cp "" 2> /dev/null
else # bash
type -P "" # No output if not in $PATH
fi
}
Non-zero est retourné si la commande ne se trouve pas dans $PATH
.