Determinar si el comando se reconoce en un archivo por lotes

43

Estoy escribiendo un script de murciélago en el que invoco un programa (como javac). Para simplificar, quiero verificar si el comando existe antes de ejecutarlo. es decir, si el comando existe en PATH.

Por ejemplo,

if (my_command.exe is a recognized command) then (
  my_command.exe my_args
) else (
  REM Output was probably "'my_command.exe' is not recognized as an internal or external command, operable program or batch file."
  REM Do not run my_command.exe
)

¿Cuál es la mejor manera de hacer esto en Windows?

user46097
fuente
¿Cómo va a "reconocer" su comando?
Grajo el
En MS-DOS (verdadero DOS) esto era bastante simple; acabas de comprobar la existencia de un archivo exe en c: \ dos; pero aun así la pregunta permanece.
Rook
Perdón por la confusion. Me refería esencialmente a un símbolo del sistema en Windows. Si escribo "lkajsflksajdfj", quiero detectar que no es un comando. Si escribo "notepad.exe", está bien.
user46097

Respuestas:

54
WHERE mycommand
IF %ERRORLEVEL% NEQ 0 ECHO mycommand wasn't found 
Josh Santangelo
fuente
10
Si alguien no quiere la salida dentro de la ventana cmd, simplemente agregue >nul 2>nuldetrás de mycommand.
Sebastian
Tenga en cuenta que hay más canales de salida que 1 y 2, ya que 1 representa el búfer de salida y 2 el búfer de error, depende de cómo se desarrolló la aplicación, debería funcionar para aplicaciones comunes que se incluyen con Windows, pero un programa CLI específico podría todavía arroja texto cuando los canales 1 y 2 son redirigidos.
ElektroStudios
15

El siguiente código siempre debe ejecutarse limpiamente sin salida de basura.

javac -version >nul 2>&1 && (
    echo found javac
) || (
    echo fail
)

Salida:

found javac

El mismo código que una línea:

javaz -version >nul 2>&1 && ( echo found javac ) || ( echo fail )

Salida:

fail

Tenga en cuenta que el orden de &&y ||parece importar. Además, el comando cuya existencia está probando debe regresar con un nivel de error <= 0 para que esto funcione. Esperemos que el comando tenga /? o --ayuda argumentos o, como con java, un comando de información de versión.

ngreen
fuente
¡Esta solución es perfecta!
robe007
7

La forma más fácil es simplemente ejecutar el comando, pero eso tiene otros problemas, por supuesto, ya que tal vez no desee que se inicie un proceso aleatorio.

for %%x in (my_command.exe) do if not [%%~$PATH:x]==[] set MyCommandFound=1

es una alternativa que busca el programa en las rutas enumeradas por la %PATH%variable de entorno. Es esencialmente una versión pura por lotes de which(1). Se puede hacer mejor, pero esencialmente esto es todo.

Joey
fuente
1
¡Esto es perfecto, hace exactamente lo que se le pidió!
Pez Cuckow
3

Por mi situación La forma más simple es usar el || o operador &&.

my_command.exe -version 2>NUL && echo "my_command exists"

o

my_command.exe -version 2>NUL || echo "my_command doesn't exist"
user46097
fuente
¿Por qué no redirige stdout también?
Joey
3

Algunas mejoras a la versión a continuación. Pruebe que ese comando existe y suprima la salida innecesaria.

WHERE scp >nul 2>nul
IF %ERRORLEVEL% EQU 0 ECHO scp found
yuliskov
fuente
donde <my_exe> NUL 2> & 1 || echo my.exe no existe && goto: EOF funciona bien en los scripts
Robert
Nota: esto no funciona si el nombre del archivo que desea probar incluye información de ruta. Por ejemplo, WHERE \Windows\System32\cmd.exe=>INFO: Could not find files for the given pattern(s).
Jonathan Gilbert el
1

Si se requiere la instalación de herramientas adicionales, hay un wherecomando en los kits de recursos; ¿Ver el equivalente de Windows de whereis? .

De lo contrario, para versiones de Windows que no son demasiado antiguas, es factible en estado puro cmd, como se menciona en la búsqueda ejecutable de DOS, excepto PATH .

Gilles 'SO- deja de ser malvado'
fuente
Gracias por la respuesta! Desafortunadamente, uno de los requisitos es que debe ejecutarse en una caja de vainilla (máquinas XP incluidas), por lo que no es una opción.
user46097
2
El segundo enlace que Gilles dio tiene una solución ingeniosa que usa FOR y no tiene herramientas adicionales.
paradroid
1

Sé que esto no es exactamente lo que está buscando, pero con un ligero cambio en la lógica, debería lograr lo que necesita.

Cada comando que se ejecuta tiene un código de retorno (también conocido como errorlevel), si el código de retorno es 0 (cero), el comando se ejecutó con éxito, si el código de retorno es mayor que 0, algo salió mal.

Ver aquí para más detalles.

Algo como -

my_command
if (%ERRORLEVEL% > 0) then (
  REM Output was probably "'my_command.exe' is not recognized as an internal or external command, operable program or batch file.  OR SOMETHING WENT WRONG WITH IT."
  REM Do not run my_command.exe
)
Bryan
fuente
Esto es inteligente, me gusta.
Shinrai
Sí, pero es feo desde entonces, si no se encuentra el comando, arroja un error de 2 líneas. Por lo tanto, posiblemente se pueda encontrar una solución más limpia.
djangofan
0

Si bien todas esas formas podrían funcionar, ¿por qué no las incorporadas?

If exists my_command do echo "my_command exists"

Ejecute "si /?" en la línea de comando para más detalles

uSlackr
fuente
55
Esto solo verá si existe un archivo / directorio con ese nombre en el directorio actual. No proporciona mucha pista sobre si existe un comando ejecutable con ese nombre porque para determinar que tendría que buscar en el PATH.
Joey