¿Cómo pruebo para ver si existe una aplicación en $ PATH?

19

Estoy tratando de escribir todos mis shscripts de inicio / env para trabajar con DRY y tanto: "funciona en cada * nix en el que lo clono", como sea posible. Esto significa asegurarse de que si trato de ejecutar el código que no está allí, el código falla correctamente. Para ello necesito poder probar si existen programas. Sé cómo probar si existe un archivo, pero no estoy seguro de cómo hacerlo para ver si una aplicación es ejecutable dentro de la ruta. Prefiero usar $ PATH, ya que algunos de estos necesitan trabajar en arch, ubuntu y centos. Algunos pueden instalarse en mi homedir, en sistemas donde no tengo root, otros pueden no instalarse y otros aún pueden instalarse en las rutas del sistema.

xenoterracida
fuente
2
Esta respuesta SO es la que he marcado para tales preguntas.
jw013

Respuestas:

19

Uso type commandname. Esto devuelve verdadero si commandnamehay algo ejecutable: alias, función, comando incorporado o externo (buscado en $PATH). Alternativamente, use command commandnamewhich return true si commandnamees un comando incorporado o externo (buscado en $PATH).

exists () {
  type "$1" >/dev/null 2>/dev/null
}

Hay algunas variantes sh (definitivamente pre-POSIX; conozco /bin/shbajo OSF1 ≤3.xy algunas versiones del shell Almquist que se encuentran en las primeras versiones de NetBSD y algunas distribuciones Linux del siglo XX) donde typesiempre devuelve 0 o no existe. No creo que haya ningún sistema enviado con estos este milenio. Si alguna vez los encuentra, aquí hay una función que puede usar para buscar $PATHmanualmente:

exists () { (
    IFS=:
    for d in $PATH; do
      if test -x "$d/$1"; then return 0; fi
    done
    return 1
) }

Esta función es generalmente útil si desea excluir funciones y funciones incorporadas y buscar el nombre $PATH. La mayoría de los shells tienen una función incorporada para esto, command -vaunque es una adición relativamente reciente a POSIX (todavía opcional a partir de POSIX: 2004). Básicamente es una versión amigable para el programador type: imprime la ruta completa para un ejecutable $PATH, el nombre para una función o función incorporada y una definición de alias para un alias.

exists_in_path () {
  case $(command -v -- "$1") in
    /*) return 0;;
    alias\ *) return 1;; # alias
    *) return 1;; # built-in or function
  esac
}

Ksh, bash y zsh también tienen type -pque buscar solo ejecutables en $PATH. Tenga en cuenta que en bash, el estado de retorno de type -p fooes 0 si fooes una función o incorporada; si desea probar un archivo ejecutable $PATH, debe verificar que la salida no esté vacía. type -pno está en POSIX; por ejemplo, la ceniza de Debian (que está /bin/shen Ubuntu) no la tiene.

Gilles 'SO- deja de ser malvado'
fuente
@gilles, ¿esto (o algo similar) if [ type keychain ]; thenno funcionará? Me sale error /home/xenoterracide/.zshrc:84: parse error: condition expected: typesupongo que podría escribir la función existe ... Sólo pensé que esto podría ser más simple en un sentido ...
xenoterracide
@xenoterracide: ¡Suelta los corchetes!
Gilles 'SO- deja de ser malvado'
Creo que estás buscando if type $APP >/dev/null 2>/dev/null; then ...No quieres el [].
Steven D
44
Bah, sabía que debería haberme refrescado. ¡Golpeado por Gilles otra vez!
Steven D
type -psi está buscando específicamente un comando en $PATH(no alias o funciones o incorporados).
Ephemient
1

Si solo está buscando programas externos, también puede usar cuáles. Sin embargo, no sé cuán portátil es eso.

Kim
fuente
3
En teoría, es menos portátil que typeo command; whichno está en POSIX, por ejemplo. En la práctica, whichexiste en casi todas partes, pero en algunos lugares (donde se implementa como un script csh) utiliza una ruta diferente (debido a a .cshrc), lo que anula el propósito.
Gilles 'SO- deja de ser malo'