¿Cómo puedo comprobar si existe un programa desde un script Bash?

Resuelto gregh asked hace 15 años • 39 respuestas

¿Cómo validaría que existe un programa, de manera que devuelva un error y salga, o continúe con el script?

Parece que debería ser fácil, pero me ha dejado perplejo.

gregh avatar Feb 27 '09 04:02 gregh
Aceptado

Respuesta

Compatible con POSIX:

command -v <the_command>

Uso de ejemplo:

if ! command -v <the_command> &> /dev/null
then
    echo "<the_command> could not be found"
    exit 1
fi

Para entornos específicos de Bash:

hash <the_command> # For regular commands. Or...
type <the_command> # To check built-ins and keywords

Explicación

Evitar which. No solo es un proceso externo que estás iniciando para hacer muy poco (lo que significa que las funciones integradas como hash, typeo commandson mucho más baratas), también puedes confiar en las funciones integradas para hacer lo que quieres, mientras que los efectos de los comandos externos pueden variar fácilmente de sistema a sistema.

¿Por qué preocuparse?

  • Muchos sistemas operativos tienen un whichque ni siquiera establece un estado de salida , lo que significa que if which fooni siquiera funcionará allí y siempre informará que fooexiste, incluso si no es así (tenga en cuenta que algunos shells POSIX parecen hacer esto hashtambién).
  • Muchos sistemas operativos hacen whichcosas personalizadas y malvadas, como cambiar la salida o incluso conectarse al administrador de paquetes.

Así que no uses which. En su lugar, utilice uno de estos:

command -v foo >/dev/null 2>&1 || { echo >&2 "I require foo but it's not installed.  Aborting."; exit 1; }
type foo >/dev/null 2>&1 || { echo >&2 "I require foo but it's not installed.  Aborting."; exit 1; }
hash foo 2>/dev/null || { echo >&2 "I require foo but it's not installed.  Aborting."; exit 1; }

(Nota al margen menor: algunos sugerirán 2>&-que es lo mismo 2>/dev/nullpero más corto; esto no es cierto . 2>&-Cierra FD 2, lo que provoca un error en el programa cuando intenta escribir en stderr, lo cual es muy diferente a escribirlo con éxito y descartar la salida. (¡y peligroso!))

Si tu hash bang es /bin/shentonces deberías preocuparte por lo que dice POSIX. typey hashlos códigos de salida de POSIX no están muy bien definidos y hashse ve que salen exitosamente cuando el comando no existe (aún no he visto esto type). commandEl estado de salida de está bien definido por POSIX, por lo que probablemente sea el más seguro de usar.

Sin embargo, si su script lo usa bash, las reglas POSIX ya no importan y ambas typese hashvuelven perfectamente seguras de usar. typeahora tiene un -Ppara buscar solo PATHy hashtiene el efecto secundario de que la ubicación del comando será codificada (para una búsqueda más rápida la próxima vez que lo use), lo cual generalmente es algo bueno ya que probablemente verifique su existencia para poder usarlo realmente. .

Como ejemplo simple, aquí hay una función que se ejecuta gdatesi existe; de ​​lo contrario date:

gnudate() {
    if hash gdate 2>/dev/null; then
        gdate "$@"
    else
        date "$@"
    fi
}

Alternativa con un conjunto completo de funciones

Puede utilizar scripts comunes para satisfacer sus necesidades.

Para comprobar si hay algo instalado, puedes hacer:

checkBin <the_command> || errorMessage "This tool requires <the_command>. Install it please, and then run this tool again."
lhunath avatar Mar 24 '2009 12:03 lhunath

La siguiente es una forma portátil de comprobar si un comando existe $PATH y es ejecutable:

[ -x "$(command -v foo)" ]

Ejemplo:

if ! [ -x "$(command -v git)" ]; then
  echo 'Error: git is not installed.' >&2
  exit 1
fi

La verificación del ejecutable es necesaria porque bash devuelve un archivo no ejecutable si no se encuentra ningún archivo ejecutable con ese nombre en $PATH.

También tenga en cuenta que si existe un archivo no ejecutable con el mismo nombre que el ejecutable anteriormente en $PATH, el guión devuelve el primero, aunque el segundo se ejecutaría. Esto es un error y viola el estándar POSIX. [ Informe de error ] [ Estándar ]
Editar : Esto parece estar solucionado a partir de Dash 0.5.11 (Debian 11).

Además, esto fallará si el comando que busca se ha definido como alias.

Alexia avatar Nov 05 '2014 14:11 Alexia

Estoy de acuerdo con lhunath en desalentar el uso de which, y su solución es perfectamente válida para los usuarios de Bash . Sin embargo, para que sea más portátil, command -vse utilizará en su lugar:

$ command -v foo >/dev/null 2>&1 || { echo "I require foo but it's not installed.  Aborting." >&2; exit 1; }

El comando commandes compatible con POSIX. Consulte aquí para conocer su especificación: comando: ejecute un comando simple

Nota: typees compatible con POSIX, pero type -Pno lo es.

GregV avatar Jan 24 '2011 18:01 GregV

Depende de si desea saber si existe en uno de los directorios de la $PATHvariable o si conoce su ubicación absoluta. Si quieres saber si está en la $PATHvariable, usa

if which programname >/dev/null; then
    echo exists
else
    echo does not exist
fi

de lo contrario usar

if [ -x /path/to/programname ]; then
    echo exists
else
    echo does not exist
fi

La redirección a /dev/null/en el primer ejemplo suprime la salida del whichprograma.

dreamlax avatar Feb 26 '2009 22:02 dreamlax