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?


¿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 

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.


¡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.


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"

¿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

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 .


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
)

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


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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.