¿Cómo puedo comprobar si existe un programa a partir de un script Bash?
Frecuentes
Visto 784,280 equipos
30 Respuestas
3401
Respuesta
Compatible con POSIX:
command -v <the_command>
Ejemplo de uso:
if ! command -v COMMAND &> /dev/null
then
echo "COMMAND could not be found"
exit
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
Evitando which
. No solo es un proceso externo que está iniciando para hacer muy poco (es decir, incorporaciones como hash
, type
or command
son mucho más baratos), también puede confiar en las funciones integradas para hacer realmente lo que desee, mientras que los efectos de los comandos externos pueden variar fácilmente de un sistema a otro.
¿Por qué importa?
- Muchos sistemas operativos tienen
which
esta ni siquiera establece un estado de salida, significando elif which foo
ni siquiera funcionará allí y lo hará siempre informar de quefoo
existe, incluso si no lo hace (tenga en cuenta que algunos shells POSIX parecen hacer esto parahash
también). - Muchos sistemas operativos hacen
which
hacer cosas personalizadas y malvadas como cambiar la salida o incluso conectarse al administrador de paquetes.
Entonces, no uses which
. En su lugar, use 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>&-
es el mismo 2>/dev/null
pero más corto - esto es falso. 2>&-
cierra FD 2 lo que provoca una error en el programa cuando intenta escribir en stderr, que es muy diferente de escribir con éxito y descartar la salida (¡y peligroso!))
Si tu hash bang es /bin/sh
entonces debería preocuparse por lo que dice POSIX. type
y hash
Los códigos de salida no están muy bien definidos por POSIX, y hash
se ve salir con éxito cuando el comando no existe (no he visto esto con type
todavía). command
El estado de salida está bien definido por POSIX, por lo que probablemente uno sea el más seguro de usar.
Si su secuencia de comandos usa bash
sin embargo, las reglas POSIX ya no importan y tanto type
y hash
sea perfectamente seguro de usar. type
ahora tiene un -P
para buscar solo el PATH
y hash
tiene el efecto secundario de que la ubicación del comando será hash (para una búsqueda más rápida la próxima vez que lo use), lo cual suele ser algo bueno, ya que probablemente verifique su existencia para poder usarlo realmente.
Como ejemplo simple, aquí hay una función que se ejecuta gdate
si existe, de lo contrario date
:
gnudate() {
if hash gdate 2>/dev/null; then
gdate "$@"
else
date "$@"
fi
}
Alternativa con un conjunto completo de funciones
Puedes usar scripts-comunes para alcanzar su necesidad.
Para comprobar si hay algo instalado, puede hacer:
checkBin <the_command> || errorMessage "This tool requires <the_command>. Install it please, and then run this tool again."
Respondido 01 Jul 20, 08:07
@Geert: La parte &> / dev / null oculta el mensaje que 'type' emite cuando 'foo' no existe. El> & 2 en el eco se asegura de enviar el mensaje de error al error estándar en lugar de la salida estándar; porque eso es una convención. Ambos aparecen en su terminal, pero el error estándar es definitivamente la salida preferida para mensajes de error y advertencias inesperadas. - lhunath
la bandera -P no funciona en 'sh', p. ej. stackoverflow.com/questions/2608688/… - Momeara
Para aquellos que no están familiarizados con la redirección de E / S 'avanzada' en bash: 1) 2>&-
("cerrar el descriptor de archivo de salida 2", que es stderr) tiene el mismo resultado que 2> /dev/null
; 2) >&2
es un atajo para 1>&2
, que puede reconocer como "redireccionar stdout a stderr". Ver el Página de redirección de E / S de la Guía avanzada de Bash Scripting para más información. - mikewaters
@mikewaters El ABS parece bastante avanzado y describe una amplia gama de funciones CLI bash y no bash, pero es muy negligente en muchos aspectos y no sigue las buenas prácticas. No tengo suficiente espacio en este comentario para escribir una reseña; pero puedo pegar algunos ejemplos aleatorios de código MALO: while read element ; do .. done <<< $(echo ${ArrayVar[*]})
, for word in $(fgrep -l $ORIGINAL *.txt)
, ls -l "$directory" | sed 1d
, {{por un en seq $BEGIN $END
}}, ... Muchos han intentado contactar a los autores y proponer mejoras pero no es wiki y las solicitudes han caído en oídos sordos. - lhunath
@mikewaters 2>&-
is no lo mismo que 2>/dev/null
. El primero cierra el descriptor del archivo, mientras que el segundo simplemente lo redirige a /dev/null
. Es posible que no vea un error porque el programa intenta informarle en stderr que stderr está cerrado. - nyuszika7h
642
La siguiente es una forma portátil de comprobar si existe un comando en $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 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 un archivo no ejecutable con el mismo nombre que el ejecutable existe anteriormente en $PATH
, dash devuelve el primero, aunque se ejecute el último. Esto es un error y viola el estándar POSIX. [Informe de error] [Estándar]
Además, esto fallará si el comando que está buscando se ha definido como un alias.
Respondido 26 Oct 17, 15:10
Testamento command -v
producir una ruta incluso para un archivo no ejecutable? Es decir, ¿la -x es realmente necesaria? - einpoklum
@einpoklum -x
prueba que el archivo es ejecutable, que es la pregunta. - ken agudo
@KenSharp: Pero eso parece ser redundante, ya que command
probará si es ejecutable, ¿no es así? - einpoklum
@einpoklum Sí, es necesario. De hecho, incluso esta solución puede romperse en un caso de borde. Gracias por informarme sobre esto. dash, bash y zsh omiten archivos no ejecutables en $PATH
al ejecutar un comando. Sin embargo, el comportamiento de command -v
es muy inconsistente. En guión, devuelve el primer archivo coincidente en $PATH
, independientemente de si es ejecutable o no. En bash, devuelve la primera coincidencia ejecutable en $PATH
, pero si no hay ninguno, puede devolver un archivo no ejecutable. Y en zsh, nunca devolverá un archivo no ejecutable. - nyuszika7h
Por lo que yo puedo decir, dash
es el único de esos tres que no cumple con POSIX; [ -x "$(command -v COMMANDNAME)"]
funcionará en los otros dos. Parece que este error ya se ha informado, pero aún no ha recibido ninguna respuesta: bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264 - nyuszika7h
215
Estoy de acuerdo con lhunath para desalentar el uso de which
, y su solución es perfectamente válida para usuarios de Bash. Sin embargo, para ser más portátil, command -v
se utilizará en su lugar:
$ command -v foo >/dev/null 2>&1 || { echo "I require foo but it's not installed. Aborting." >&2; exit 1; }
Comando command
es compatible con POSIX. Vea aquí su especificación: comando - ejecutar un comando simple
Nota: type
es compatible con POSIX, pero type -P
no es.
Respondido el 16 de enero de 20 a las 03:01
Lo mismo que arriba - exit 1;
mata un xterm, si se invoca desde allí. - usuario desconocido
Esto no funcionaría en un estándar sh: you &> no es una instrucción de redireccionamiento válida. - jyavenard
@jyavenard: la pregunta está etiquetada golpear, de ahí la notación de redireccionamiento más concisa específica de bash &>/dev/null
. Sin embargo, estoy de acuerdo con usted, lo que realmente importa es la portabilidad, he editado mi respuesta en consecuencia, ahora usando la redirección estándar de sh >/dev/null 2>&1
. - gregv
para mejorar aún más esta respuesta, haría dos cosas: 1: usar "&>" para simplificarlo, como la respuesta de Josh. 2: divida el {} en una línea adicional, colocando una pestaña antes del eco, para facilitar la lectura - Knocte
Acabo de poner este trazador de líneas en una función bash si alguien lo quiere ... github.com/equant/my_bash_tools/blob/master/tarp.bash - igual
95
Tengo una función definida en mi .bashrc que facilita esto.
command_exists () {
type "$1" &> /dev/null ;
}
Aquí hay un ejemplo de cómo se usa (de mi .bash_profile
.)
if command_exists mvim ; then
export VISUAL="mvim --nofork"
fi
Respondido 14 Oct 10, 10:10
¿Qué hace el &>
¿hacer? - Saad Malik
El &>
redirige tanto stdout como stderr juntos. - Josh Strater
&>
puede no estar disponible en su versión de Bash. El código de Marcello debería funcionar bien; hace la misma cosa. - Josh Strater
Falla en palabras integradas y reservadas: intente esto con la palabra then
por ejemplo. Ver esta respuesta si necesita que el ejecutable exista en $PATH
. - tom hale
89
Depende de si desea saber si existe en uno de los directorios del $PATH
variable o si conoce la ubicación absoluta de la misma. Si quieres saber si está en el $PATH
variable, uso
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 which
.
Respondido el 16 de enero de 20 a las 03:01
Realmente no debería usar "which" por las razones descritas en mi comentario. - lhunath
40
Ampliando las respuestas de @ lhunath y @ GregV, aquí está el código para las personas que quieren poner fácilmente ese cheque dentro de un if
declaración:
exists()
{
command -v "$1" >/dev/null 2>&1
}
He aquí cómo usarlo:
if exists bash; then
echo 'Bash exists!'
else
echo 'Your system does not have Bash'
fi
Respondido el 11 de diciembre de 15 a las 20:12
La voluntad de aprender y mejorar debe ser recompensada. +1 Esto es limpio y simple. Lo único que puedo agregar es que command
tiene éxito incluso para los alias, lo que podría ser algo contrario a la intuición. Verificar la existencia en un shell interactivo dará resultados diferentes a los de cuando lo mueve a un script. - Dedo
Acabo de probar y usar shopt -u expand_aliases
ignora / oculta los alias (como el alias ls='ls -F'
mencionado en otra respuesta) y shopt -s expand_aliases
los resuelve a través de command -v
. Entonces, quizás debería establecerse antes de la verificación y desarmarse después, aunque podría afectar el valor de retorno de la función si no captura y devuelve el resultado de la llamada de comando explícitamente. - dragon788
¿Por qué esto no funciona en if exists conda; then
, a pesar de que anaconda está instalado y devuelve: usage: conda [-h] [-V] command...
cuando uno entra conda
en la terminal? (Tenga en cuenta que verifiqué que su respuesta funciona con if exists bash; then
en un sistema operativo Ubuntu 20.) - a
24
Intente usar:
test -x filename
or
[ -x filename ]
Desde la página de manual de Bash en Expresiones condicionales:
-x file True if file exists and is executable.
Respondido el 16 de enero de 20 a las 03:01
Eso significa que necesita conocer ya la ruta completa a la aplicación. - lhunath
El OP no especificó si quería buscar una instancia específica o cualquier instancia ejecutable ... Lo respondí de la forma en que lo leí. - dmckee --- ex-gatito moderador
17
Para utilizar hash
, como sugiere @lhunath, en un script de Bash:
hash foo &> /dev/null
if [ $? -eq 1 ]; then
echo >&2 "foo not found."
fi
Este script se ejecuta hash
y luego verifica si el código de salida del comando más reciente, el valor almacenado en $?
, es igual a 1
. Si hash
no encuentra foo
, el código de salida será 1
. Si foo
está presente, el código de salida será 0
.
&> /dev/null
redirecciones Error estándar y salida estándar del hash
para que no aparezca en pantalla y echo >&2
escribe el mensaje en error estándar.
Respondido el 16 de enero de 20 a las 03:01
¿Por qué no solo if hash foo &> /dev/null; then ...
? - Beni Cherniavsky-Paskin
9
Si comprueba la existencia del programa, probablemente lo ejecutará más tarde de todos modos. ¿Por qué no intentar ejecutarlo en primer lugar?
if foo --version >/dev/null 2>&1; then
echo Found
else
echo Not found
fi
Es una verificación más confiable que el programa se ejecute que simplemente mirar los directorios PATH y los permisos de los archivos.
Además, puede obtener algunos resultados útiles de su programa, como su versión.
Por supuesto, los inconvenientes son que algunos programas pueden ser pesados al iniciar y otros no tienen --version
opción para salir inmediatamente (y con éxito).
Respondido 08 Jul 13, 16:07
9
Nunca obtuve las respuestas anteriores para trabajar en el cuadro al que tengo acceso. Para uno, type
ha sido instalado (haciendo lo que more
lo hace). Por tanto, se necesita la directiva incorporada. Este comando funciona para mí:
if [ `builtin type -p vim` ]; then echo "TRUE"; else echo "FALSE"; fi
Respondido el 16 de enero de 20 a las 03:01
Los corchetes no forman parte del if
sintaxis, simplemente use if builtin type -p vim; then ...
. Y las comillas inversas son una sintaxis realmente antigua y obsoleta, $()
es apoyado incluso por sh
en todos los sistemas modernos. - nyuszika7h
9
Verifique múltiples dependencias e informe el estado a los usuarios finales
for cmd in latex pandoc; do
printf '%-10s' "$cmd"
if hash "$cmd" 2>/dev/null; then
echo OK
else
echo missing
fi
done
Muestra de salida:
latex OK
pandoc missing
Ajustar el 10
a la longitud máxima del comando. No es automático, porque no veo una forma POSIX no detallada de hacerlo:
¿Cómo puedo alinear las columnas de una tabla separada por espacios en Bash?
Compruebe si algunos apt
los paquetes se instalan con dpkg -s
e instalarlos de otra manera.
Ver: Compruebe si hay un paquete apt-get instalado y luego instálelo si no está en Linux
Se mencionó anteriormente en: ¿Cómo puedo comprobar si existe un programa a partir de un script Bash?
Respondido el 16 de enero de 20 a las 03:01
Manera no detallada de hacerlo: 1) deshacerse del especificador de ancho; 2) agregue un espacio después de printf del nombre de su comando; 3) canaliza tu bucle for a column -t
(parte de util-linux). - Patrice Levesque
7
hash foo 2>/dev/null
: funciona con shell Z (Zsh), Bash, Dash y ceniza.
type -p foo
: parece funcionar con Z shell, Bash y ash (BusyBox), pero no Dash (interpreta -p
como argumento).
command -v foo
: funciona con shell Z, Bash, Dash, pero no ash (BusyBox) (-ash: command: not found
).
También tenga en cuenta que builtin
no está disponible con Ash y Dash.
Respondido el 16 de enero de 20 a las 03:01
Gran lista. ¿De qué versiones? En mi sistema command -v foo
trabaja en busybox sh
(BusyBox v1.22.1 (Debian 1: 1.22.0-19 + b3) shell integrado (ash)). Falla correctamente con 127 cuando no se encuentra foo e imprime la ruta si lo encuentra. - simohe
7
Hay un montón de opciones aquí, pero me sorprendió que no hubiera una sola línea rápida. Esto es lo que usé al comienzo de mis scripts:
[[ "$(command -v mvn)" ]] || { echo "mvn is not installed" 1>&2 ; exit 1; }
[[ "$(command -v java)" ]] || { echo "java is not installed" 1>&2 ; exit 1; }
Esto se basa en la respuesta seleccionada aquí y en otra fuente.
Respondido el 16 de enero de 20 a las 12:01
7
Comando -v
funciona bien si la opción POSIX_BUILTINS está configurada para el <command>
para probar, pero puede fallar si no. (Me ha funcionado durante años, pero recientemente me encontré con uno en el que no funcionó).
Encuentro que lo siguiente es más a prueba de fallas:
test -x "$(which <command>)"
Ya que prueba tres cosas: ruta, existencia y permiso de ejecución.
Respondido el 17 de diciembre de 20 a las 20:12
No funciona. test -x $(which ls)
devuelve 0, al igual que test -x $(which sudo)
, aunque ls
está instalado y ejecutable y sudo
ni siquiera está instalado dentro del contenedor de la ventana acoplable en el que estoy ejecutando. alga
@algal Necesitas usar comillas, creo, así que test -x "$(which <command>)"
- jonivr
@algal Quizás ls
tiene un alias? No creo que funcione si el comando tiene parámetro. - antonioc
No puedo responder por esta respuesta, pero también recomendaría citas. $ test -x $(which absent_cmd)
devoluciones test: too many arguments
, mientras test -x "$(which absent_cmd)"
se analiza correctamente y da como resultado el código de salida 1. - protobooleano
4
Utilice incorporados de Bash si puede:
which programname
...
type -P programname
Respondido el 16 de enero de 20 a las 03:01
¿Eh? which
no es un Bash incorporado. - triples
escriba -P nombre de programa es preferible, consulte la respuesta aceptada - RobertoG
@RobertG Todo lo que veo es que -P
no es POSIX. Por que es type -P
¿privilegiado? - mikemaccana
Debería haber dicho que "ser preferido en entornos bash", ya que tenía la intención de responder al comentario anterior específico de bash. De todos modos, eso fue hace años. Supongo que debería, de nuevo, señalarte la respuesta marcada como "aceptada". RobertoG
4
Para los interesados, ninguna de las metodologías de las respuestas anteriores funciona si desea detectar una biblioteca instalada. Me imagino que le queda comprobar físicamente la ruta (potencialmente para archivos de encabezado y demás), o algo así (si está en una distribución basada en Debian):
dpkg --status libdb-dev | grep -q not-installed
if [ $? -eq 0 ]; then
apt-get install libdb-dev
fi
Como puede ver en lo anterior, una respuesta "0" de la consulta significa que el paquete no está instalado. Esta es una función de "grep": un "0" significa que se encontró una coincidencia, un "1" significa que no se encontró ninguna coincidencia.
Respondido el 16 de enero de 20 a las 03:01
Sin embargo, el anti-patrón cmd; if [ $? -eq 0 ]; then
debería ser refactorizado a if cmd; then
- triples
Esto solo funciona para bibliotecas instaladas a través de dpkg
or apt
- Weijun Zhou
2
Yo diría que no hay ninguna forma portátil y 100% confiable debido a que cuelga alias
es. Por ejemplo:
alias john='ls --color'
alias paul='george -F'
alias george='ls -h'
alias ringo=/
Por supuesto, solo el último es problemático (¡sin ofender a Ringo!). Pero todos son validos alias
es desde el punto de vista de command -v
.
Para rechazar los colgantes como ringo
, tenemos que analizar la salida del shell incorporado alias
comando y recurrir a ellos (command -v
no es superior a alias
aquí.) No hay ninguna solución portátil para ello, e incluso una solución específica de Bash es bastante tediosa.
Tenga en cuenta que una solución como esta rechazará incondicionalmente alias ls='ls -F'
:
test() { command -v $1 | grep -qv alias }
Respondido el 16 de enero de 20 a las 12:01
Buen punto. Sin embargo, cuando se ejecuta desde dentro de un script bash, los alias no son visibles. - Albahaca Musa
También hay un problema, devolverá falso cuando se marque el comando 'alias'. Cuándo debería volver a ser verdadero. Ejemplo: prueba "alias" - Albahaca Musa
Acabo de probar y usar shopt -u expand_aliases
ignora / oculta estos alias y shopt -s expand_aliases
les muestra a través de command -v
. - dragon788
2
Esto le dirá según la ubicación si el programa existe o no:
if [ -x /usr/bin/yum ]; then
echo "This is Centos"
fi
Respondido 07 Abr '20, 13:04
Sí, agregué este comando si necesita instalar un paquete en el servidor, Open suse, centos, Debian - Klevin Kona
El resaltado de sintaxis está desactivado en la línea "echo". ¿Cuál es la solución? ¿Sugiere que el script de Bash debería ser diferente? - Pedro Mortensen
@PeterMortensen El resaltado de sintaxis está desactivado porque no reconoce que es una cadena. - Adrien
1
Mi configuración para un Debian servidor:
Tuve el problema cuando varios paquetes contenían el mismo nombre.
Por ejemplo: apache2
. Entonces esta fue mi solución:
function _apt_install() {
apt-get install -y $1 > /dev/null
}
function _apt_install_norecommends() {
apt-get install -y --no-install-recommends $1 > /dev/null
}
function _apt_available() {
if [ `apt-cache search $1 | grep -o "$1" | uniq | wc -l` = "1" ]; then
echo "Package is available : $1"
PACKAGE_INSTALL="1"
else
echo "Package $1 is NOT available for install"
echo "We can not continue without this package..."
echo "Exitting now.."
exit 0
fi
}
function _package_install {
_apt_available $1
if [ "${PACKAGE_INSTALL}" = "1" ]; then
if [ "$(dpkg-query -l $1 | tail -n1 | cut -c1-2)" = "ii" ]; then
echo "package is already_installed: $1"
else
echo "installing package : $1, please wait.."
_apt_install $1
sleep 0.5
fi
fi
}
function _package_install_no_recommends {
_apt_available $1
if [ "${PACKAGE_INSTALL}" = "1" ]; then
if [ "$(dpkg-query -l $1 | tail -n1 | cut -c1-2)" = "ii" ]; then
echo "package is already_installed: $1"
else
echo "installing package : $1, please wait.."
_apt_install_norecommends $1
sleep 0.5
fi
fi
}
Respondido el 16 de enero de 20 a las 03:01
1
Si ustedes chicos / chicas no pueden hacer que las cosas en las respuestas aquí funcionen y se están arrancando el pelo de la espalda, intente ejecutar el mismo comando usando bash -c
. Basta con mirar este delirio sonámbulo. Esto es lo que realmente sucede cuando ejecuta $ (subcomando):
Primero. Puede darle una salida completamente diferente.
$ command -v ls
alias ls='ls --color=auto'
$ bash -c "command -v ls"
/bin/ls
Segundo. No le puede dar ningún resultado.
$ command -v nvm
nvm
$ bash -c "command -v nvm"
$ bash -c "nvm --help"
bash: nvm: command not found
Respondido el 16 de enero de 20 a las 11:01
Las diferencias se deben a la diferencia entre el modo interactivo y no interactivo del shell. Su ~ / .bashrc es de solo lectura cuando el shell no es de inicio de sesión y es interactivo. Sin embargo, el segundo parece extraño, porque debe ser causado por una diferencia en la variable de entorno PATH, pero las subcapas heredan el entorno. - Dedo
En mi caso .bashrc
tiene un [ -z "$PS1" ] && return
precedido por # If not running interactively, don't do anything
así que supongo que esa es una de las razones por las que incluso el suministro explícito de bashrc en modo no interactivo no ayuda. El problema se puede solucionar llamando a un script con un ss64.com/bash/fuente.html operador de puntos . ./script.sh
pero eso no es algo que a uno le gustaría recordar escribir cada vez. - user619271
Obtener scripts que se supone que no deben obtenerse es una mala idea. Todo lo que estaba tratando de decir es que su respuesta tiene poco que ver con la pregunta que se hace y mucho que ver con Bash y su modo (no) interactivo. - Dedo
Si explicara lo que está sucediendo en estos casos, sería un apéndice útil a la respuesta. - Dedo
1
En caso de que quiera comprobar si existe un programa y es realmente un programa, no un comando integrado de Bash, entonces command
, type
y hash
no son apropiados para las pruebas, ya que todos devuelven un estado de salida 0 para los comandos integrados.
Por ejemplo, existe el equipo programa que ofrece más funciones que el equipo comando incorporado. Para verificar si el programa existe, sugeriría usar which
como en el siguiente ejemplo:
# First check if the time program exists
timeProg=`which time`
if [ "$timeProg" = "" ]
then
echo "The time program does not exist on this system."
exit 1
fi
# Invoke the time program
$timeProg --quiet -o result.txt -f "%S %U + p" du -sk ~
echo "Total CPU time: `dc -f result.txt` seconds"
rm result.txt
Respondido el 16 de enero de 20 a las 12:01
1
Quería que se respondiera la misma pregunta pero que se ejecutara dentro de un Makefile.
install:
@if [[ ! -x "$(shell command -v ghead)" ]]; then \
echo 'ghead does not exist. Please install it.'; \
exit -1; \
fi
Respondido el 04 de junio de 20 a las 10:06
1
Podría ser más simple, simplemente:
#!/usr/bin/env bash
set -x
# if local program 'foo' returns 1 (doesn't exist) then...
if ! type -P foo; then
echo 'crap, no foo'
else
echo 'sweet, we have foo!'
fi
Cambiar y guardar foo
a vi
para conseguir que la otra condición se dispare.
Respondido el 15 de junio de 20 a las 21:06
0
La variante hash tiene un problema: en la línea de comando puede, por ejemplo, escribir
one_folder/process
ejecutar el proceso. Para esto, la carpeta principal de one_folder debe estar en $ RUTA. Pero cuando intentas aplicar un hash a este comando, siempre tendrá éxito:
hash one_folder/process; echo $? # will always output '0'
Respondido el 14 de diciembre de 11 a las 12:12
"Para ello, la carpeta principal de one_folder debe estar en $PATH
"—Esto es completamente inexacto. Pruébelo. Para que esto funcione, una_carpeta debe estar en el directorio actual. - Comodín
0
Secundo el uso de "comando -v". Por ejemplo, así:
md=$(command -v mkdirhier) ; alias md=${md:=mkdir} # bash
emacs="$(command -v emacs) -nw" || emacs=nano
alias e=$emacs
[[ -z $(command -v jed) ]] && alias jed=$emacs
respondido 06 nov., 13:19
0
El which
El comando puede ser útil. hombre que
Devuelve 0 si se encuentra el ejecutable y devuelve 1 si no se encuentra o no es ejecutable:
NAME
which - locate a command
SYNOPSIS
which [-a] filename ...
DESCRIPTION
which returns the pathnames of the files which would
be executed in the current environment, had its
arguments been given as commands in a strictly
POSIX-conformant shell. It does this by searching
the PATH for executable files matching the names
of the arguments.
OPTIONS
-a print all matching pathnames of each argument
EXIT STATUS
0 if all specified commands are
found and executable
1 if one or more specified commands is nonexistent
or not executable
2 if an invalid option is specified
Lo bueno de which
es que averigua si el ejecutable está disponible en el entorno que which
se ejecuta - ahorra algunos problemas ...
Respondido el 16 de enero de 20 a las 03:01
Use cuál si está buscando un ejecutable llamado foo, pero vea mi respuesta si desea verificar un archivo / ruta / a / a / named / foo en particular. También tenga en cuenta que puede no estar disponible en algunos sistemas mínimos, aunque debería estar presente en cualquier instalación completa ... - dmckee --- ex-gatito moderador
No confíe en el estado de salida de cuál. Muchos sistemas operativos tienen un que ni siquiera establece un estado de salida que no sea 0. - lhunath
0
Tuve que comprobar si Git se instaló como parte de la implementación de nuestro CI servidor. Mi último script de Bash fue el siguiente (servidor Ubuntu):
if ! builtin type -p git &>/dev/null; then
sudo apt-get -y install git-core
fi
Respondido el 16 de enero de 20 a las 03:01
El condicional es bastante inútil, módulo el tiempo de inicio para ejecutar apt-get, ya que apt-get estará satisfecho y saldrá si git-core ya está instalado. - triples
Su tiempo de inicio no es despreciable, pero la motivación más importante es sudo
: sin el condicional, siempre se detendría y pediría la contraseña (a menos que haya hecho un sudo recientemente). Por cierto, puede ser útil hacer sudo -p "Type your password to install missing git-core: "
para que el mensaje no aparezca de la nada. - Beni Cherniavsky-Paskin
0
Para imitar a Bash type -P cmd
, podemos usar el compatible con POSIX env -i type cmd 1>/dev/null 2>&1
.
man env
# "The option '-i' causes env to completely ignore the environment it inherits."
# In other words, there are no aliases or functions to be looked up by the type command.
ls() { echo 'Hello, world!'; }
ls
type ls
env -i type ls
cmd=ls
cmd=lsx
env -i type $cmd 1>/dev/null 2>&1 || { echo "$cmd not found"; exit 1; }
Respondido el 16 de enero de 20 a las 03:01
¿Por qué se vota a favor de esto? ¿En qué sistemas funciona esto realmente para usted? type
parece ser un builtin
en la mayoría de las conchas, por lo que esto no puede funcionar porque env
usos execvp
para ejecutar command
so command
no puede ser un builtin
(Y el builtin
siempre se ejecutará en el mismo entorno). Esto me falla en bash
, ksh93
, zsh
, busybox [a]sh
y dash
todos los cuales proporcionan type
como un shell incorporado. - Adrian Fruhwirth
0
Si no hay ninguna externa type
comando disponible (como se da por sentado aquí), podemos usar compatible con POSIX env -i sh -c 'type cmd 1>/dev/null 2>&1'
:
# Portable version of Bash's type -P cmd (without output on stdout)
typep() {
command -p env -i PATH="$PATH" sh -c '
export LC_ALL=C LANG=C
cmd="$1"
cmd="`type "$cmd" 2>/dev/null || { echo "error: command $cmd not found; exiting ..." 1>&2; exit 1; }`"
[ $? != 0 ] && exit 1
case "$cmd" in
*\ /*) exit 0;;
*) printf "%s\n" "error: $cmd" 1>&2; exit 1;;
esac
' _ "$1" || exit 1
}
# Get your standard $PATH value
#PATH="$(command -p getconf PATH)"
typep ls
typep builtin
typep ls-temp
Al menos en MacOS X v10.6.8 (Snow Leopard) usando Bash 4.2.24 (2) command -v ls
no coincide con un movido /bin/ls-temp
.
Respondido el 16 de enero de 20 a las 03:01
0
Respuesta tardía, pero esto es lo que terminé haciendo.
Solo verifico si el comando que ejecuto devuelve un código de error. Si devuelve 0, significa que el programa está instalado. Además, puede usar esto para verificar la salida de un script. Tomemos, por ejemplo, este guión.
foo.sh
#!/bin/bash
echo "hello world"
exit 1 # throw some error code
Ejemplos:
# outputs something bad... and exits
bash foo.sh $? -eq 0 || echo "something bad happened. not installed" ; exit 1
# does NOT outputs nothing nor exits because dotnet is installed on my machine
dotnet --version $? -eq 0 || echo "something bad happened. not installed" ; exit 1
Básicamente, todo lo que está haciendo es verificar el código de salida de una ejecución de comando. la respuesta más aceptada a esta pregunta será verdadera incluso si el código de salida del comando no es 0.
Respondido 14 Oct 20, 21:10
No estoy 100% seguro de que su última afirmación sea correcta. La respuesta más aceptada usa el comando command
con la bandera -v
para validar rápidamente si su argumento es un comando incorporado o ejecutable que se encuentra en PATH
. Entonces la declaración if ! command -v STRING; then ...; fi
validará si STRING
es un valido comando. - kvantur
Este es un enfoque diferente en el que verifica el código de salida del último comando ejecutado. La respuesta aceptada probablemente sea la mejor para la mayoría de los casos. Esta es una alternativa si quieres profundizar más. - Tono Nam
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas bash or haz tu propia pregunta.
¿Qué es un "programa"? ¿Incluye funciones y alias?
which
devuelve verdadero para estos.type
sin argumentos, también devolverá verdadero para palabras reservadas y elementos internos de shell. Si "programa" significa "ejecutable en$PATH
", luego ver esta respuesta. - Tom HaleTambién relevante es ¿Cómo hacer 'hash -r' y actualizar todas las conchas? y ¿Cuándo repetir ejecutables en $ PATH con bash? - jww