2011-09-22 15 views
107

Estoy escribiendo mi primer script de shell. En mi script, me gustaría verificar si existe un cierto comando, y si no, instalar el ejecutable. ¿Cómo verificaría si este comando existe?¿Cómo comprobar si existe un comando en un script de shell?

if #check that foobar command doesnt exist 
then 
    #now install foobar 
fi 
+9

acaba de pasar a venir a través. Creo que esta es la misma pregunta que: http://stackoverflow.com/questions/592620/check-if-a-program-exists-from-a-bash-script, pero proporciona muchos más detalles. –

+0

@JerryTian gracias por el enlace – Andrew

+1

Posible duplicado de [Comprobar si existe un programa desde un script Bash] (https://stackoverflow.com/questions/592620/check-if-a-program-exists-from-a-bash -script) – jww

Respuesta

167

En general, que depende de su cáscara, pero si se utiliza bash, zsh, ksh o sh (conforme a lo dispuesto por el guión), la siguiente debería funcionar:

if ! type "$foobar_command_name" > /dev/null; then 
    # install foobar here 
fi 

Para un script de instalación real, Probablemente querrá estar seguro de que type no regresa correctamente en el caso cuando hay un alias foobar. En bash se podría hacer algo como esto:

if ! foobar_loc="$(type -p "$foobar_command_name")" || [ -z "$foobar_loc" ]; then 
    # install foobar here 
fi 
+0

Me gusta esta respuesta. Traté de no dejarme seducir por la imagen de ivants que me gusta aún más;) –

+1

hmm ... cuando lo cambio para decir 'si! tipo "foo">/dev/null; 'luego obtengo el resultado en la pantalla" myscript.sh: línea 12: tipo: foo: no encontrado ", sin embargo, parece funcionar porque cuando digo' si! escriba "ls">/dev/null; 'no hay salida y la sentencia if no se ejecuta (ya que devuelve verdadero). ¿Cómo puedo silenciar la salida cuando el comando no existe? – Andrew

+8

Andrew, prueba 'si! tipo "foo">/dev/null 2> & 1; ' –

28

try usando type:

type foobar 

Por ejemplo:

$ type ls 
ls is aliased to `ls --color=auto' 

$ type foobar 
-bash: type: foobar: not found 

Esto es preferible a which por algunas razones:

1) el defecto which implementaciones solamente de apoyo el -a opción que muestra todas las opciones, por lo que debe encontrar una versión alternativa para admitir los alias

2) tipo le dirá exactamente lo que está mirando (ya sea una función bash o un alias o un binario apropiado).

3) de tipo no requiere un subproceso

4) tipo no puede ser enmascarada por un binario (por ejemplo, en una máquina Linux, si crea un programa llamado which que aparece en el camino antes de la verdadera which , las cosas golpeó el ventilador. type, por el contrario, es una cáscara integrada [sí, un subordinado sin querer hizo una vez]

+2

¿Podría poner esto en forma de una instrucción if/else (una que no da salida a la consola)? – Andrew

+0

Y en algunos Linux personalizados, no existe el comando '' which ''. – Razavi

1

which <cmd>

también ver options which supports para los alias si es aplicable a su caso.

Ejemplo

$ 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: Tenga en cuenta que no todo lo que está instalado puede estar en PATH. Por lo general, para verificar si algo está "instalado" o no, uno utilizaría comandos relacionados con la instalación relevantes para el sistema operativo. P.ej. rpm -qa | grep -i "foobar" para RHEL.

+0

'which' tiene otras trampas también –

+0

Estaba empezando a leer' man type' para ver cómo es mejor ... puede ser que me puedas ahorrar algo al publicarlo aquí ... :) – Kashyap

+0

es 'help type':) –

15

Check if a program exists from a Bash script cubre muy bien. En cualquier script de shell, lo mejor es ejecutar command -v $command_name para probar si se puede ejecutar $command_name. En bash puedes usar hash $command_name, que también hashes el resultado de cualquier búsqueda de ruta, o type -P $binary_name si solo quieres ver binarios (no funciones, etc.)

11

La cuestión no especifica una concha, así que para aquellos usando fish (friendly interactive shell):

if command --search foo >/dev/null do 
    echo exists 
else 
    echo does not exist 
end 

Para compatibilidad básica POSIX, usar la bandera -v que es un alias para --search o -s.

9

cinco maneras, 4 para bash y 1 de adición para zsh:

  • type foobar &> /dev/null
  • hash foobar &> /dev/null
  • command -v foobar &> /dev/null
  • which foobar &> /dev/null
  • (($+commands[foobar])) (zsh solamente)

Puede poner cualquiera de ellos en su if cláusula. De acuerdo con mis pruebas (https://www.topbug.net/blog/2016/10/11/speed-test-check-the-existence-of-a-command-in-bash-and-zsh/), el 1er y el 3er método se recomiendan en bash y el 5to método se recomienda en zsh en términos de velocidad.

+0

[Compruebe si existe un programa desde un script Bash] (https://stackoverflow.com/q/592620/608639) específicamente desaconseja usar 'which'. – jww

0

Una función que tengo en un script de instalación hecha precisamente para este

function assertInstalled() { 
    for var in "[email protected]"; do 
     if ! which $var &> /dev/null; then 
      echo "Install $var!" 
      exit 1 
     fi 
    done 
} 

ejemplo llamada:

assertInstalled zsh vim wget python pip git cmake fc-cache 
+0

cara a cara: esto bloquea zsh como es – Alvin

+0

solo se bloqueará si está llamando esto fuera de una secuencia de comandos o fuente de la secuencia de comandos. Cambie la salida 1 para devolver 1 o algún otro código de error si lo hace. – mgild

+0

[Compruebe si existe un programa desde un script Bash] (https://stackoverflow.com/q/592620/608639) específicamente desaconseja usar 'which'. – jww

Cuestiones relacionadas