¿Cómo probar si existe un ejecutable en% PATH% desde un archivo por lotes de Windows?

90

Estoy buscando una forma sencilla de probar si existe un ejecutable en la variable de entorno PATH desde un archivo por lotes de Windows.

No se permite el uso de herramientas externas no proporcionadas por el sistema operativo. La versión mínima de Windows requerida es Windows XP.

sorin
fuente
1
posible duplicado de Cómo comprobar si un archivo existe en el lote de DOS
karlphillip
15
@karlphilip: Definitivamente no. La pregunta aquí es bastante diferente.
Joey
1
Debe marcar una respuesta aceptada.
Jeb

Respuestas:

70
for %%X in (myExecutable.exe) do (set FOUND=%%~$PATH:X)
if defined FOUND ...

Si necesita esto para diferentes extensiones, simplemente repita PATHEXT:

set FOUND=
for %%e in (%PATHEXT%) do (
  for %%X in (myExecutable%%e) do (
    if not defined FOUND (
      set FOUND=%%~$PATH:X
    )
  )
)

Podría ser que whereya exista en versiones heredadas de Windows, pero no tengo acceso a una, así que no puedo decirlo. En mi máquina también funciona lo siguiente:

where myExecutable

y regresa con un código de salida distinto de cero si no se pudo encontrar. Sin NULembargo, en un lote al que probablemente también desee redirigir la salida .

Tenga en cuenta

El análisis en .batarchivos por lotes ( ) y en la línea de comandos es diferente (porque los archivos por lotes tienen %0- %9), por lo que debe duplicar el valor de %allí. En la línea de comandos, esto no es necesario, por lo que las variables son solo %X.

Joey
fuente
1
Me gusta su enfoque, pero sería aún mejor si pudiera proporcionar la versión completa, la que también usa PATHEXT para esto.
sorin
4
Para XP, necesita el script de bucle (o descargue where.exe del RK). Vista y 7 se envían con where.exe. Sé que el OP dijo específicamente XP, pero para la posteridad, la mejor respuesta es siempre usar where myExecutable.
Ryan Bemrose
Ryan: ¿Eh? No creo que pueda analizar tu oración.
Joey
2
Soy un principiante en secuencias de comandos por lotes y no estoy seguro de lo que significa %% x. En mi sistema Windows 7 intenté escribir: para %% X en (myExecutable.exe) hacer (establecer FOUND = %% ~ $ PATH: X) y luego presionar return. Recibí esto en respuesta: C: \ Users \ James> for %% X in (cmd.exe) do (set FOUND = %% ~ $ PATH: X) %% X fue inesperado en este momento.
simgineer
3
simengineer: el análisis en archivos por lotes y en la línea de comandos es diferente (porque los archivos por lotes tienen %0- %9), por lo que debe duplicar el valor de %allí. En la línea de comandos, esto no es necesario, por lo que las forvariables son solo %x.
Joey
82

Windows Vista y versiones posteriores se envían con un programa llamado where.exeque busca programas en la ruta. Funciona así:

D:\>where notepad
C:\Windows\System32\notepad.exe
C:\Windows\notepad.exe

D:\>where where
C:\Windows\System32\where.exe

Para usarlo en un archivo por lotes, puede usar el /qconmutador, que solo establece ERRORLEVELy no produce ninguna salida.

where /q myapplication
IF ERRORLEVEL 1 (
    ECHO The application is missing. Ensure it is installed and placed in your PATH.
    EXIT /B
) ELSE (
    ECHO Application exists. Let's go!
)

O una versión abreviada simple (pero menos legible) que imprime el mensaje y sale de su aplicación:

where /q myapplication || ECHO Cound not find app. && EXIT /B
Ryan Bemrose
fuente
¡Muy bonito y sencillo! ¡Gracias!
Pawel Cioch
18

Aquí es una solución simple que los intentos de ejecutar la aplicación y manijas de cualquier error posteriormente .

file.exe /?  2> NUL
IF NOT %ERRORLEVEL%==9009 ECHO file.exe exists in path

El código de error 9009 generalmente significa archivo no encontrado.

El único inconveniente es que file.exese ejecuta realmente si se encuentra (lo que en algunos casos no es deseable).

eadmaster
fuente
24
el único inconveniente es que se ejecuta "file.exe" (que en algunos casos no es deseado)
eadmaster
6

Esto se puede lograr mediante la sustitución de parámetros.

%~$PATH:1

Esto devuelve la ruta completa del nombre del archivo ejecutable en% 1, de lo contrario una cadena vacía.

Esto no funciona con variables definidas por el usuario. Entonces, si el nombre del archivo ejecutable no es un parámetro para su secuencia de comandos, entonces necesita una subrutina. Por ejemplo:

call :s_which app.exe
if not "%_path%" == "" (
  "%_path%"
)

goto :eof

:s_which
  setlocal
  endlocal & set _path=%~$PATH:1
  goto :eof

Ver http://ss64.com/nt/syntax-args.html

Chris Noe
fuente
1
Truco interesante con setlocalpero for %%X in (myExecutable.exe) do (set FOUND=%%~$PATH:X)es una solución de una línea que se forutiliza como solución para %%~$PATH:Xevitar cally %~$PATH:1.
gavenkoa
0
@echo off
set found=
set prog=cmd.exe
for %%i in (%path%) do if exist %%i\%prog% set found=%%i
echo "%found%"
if "%found%"=="" ....
PabloG
fuente
3
No funcionará porque forno es lo suficientemente inteligente como para analizar el contenido de PATH. Perderá directorios con espacios, por ejemplo. E incluso cuando lo utilice for /fcon delims=;, no funcionará correctamente si un directorio contiene un ;y se cita.
Joey
@Joey, ¿qué tal el reemplazo de cuerdas? Reemplazar ;con "; ": set quotedPath="%PATH:;="; "%".
XP1
1
XP1: No, sigue siendo inútil. Pruébelo agregando "C:\Folder with; semicolon, quoted"a la ruta y vea qué sucede. Al menos aquí intenta tratar cada »palabra« por separado, lo que, en cierto modo, es peor que el comportamiento anterior.
Joey
0

A veces, esta solución simple funciona, donde verifica si el resultado coincide con lo que espera. La primera línea ejecuta el comando y toma la última línea de salida estándar.

FOR /F "tokens=*" %%i in (' "xcopy /? 2> nul" ') do SET xcopyoutput=%%i
if "%xcopyoutput%"=="" echo xcopy not in path.
bdombro
fuente
Pero, ¿y si el entorno del sistema usa otro idioma?
Beachwalker
0

Si está buscando algo como yo en la carpeta de inicio, debería ir a la carpeta. Por ejemplo, busco exe en la carpeta de inicio y uso este código como

@echo off
cd C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp
where /q program.exe
IF ERRORLEVEL 1 (
echo F | xcopy /Y /S /I /E "\\programsetup\programsetup.exe" 
"C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\program.exe"
) ELSE (
ECHO Application exists. Let's go!
)
Zafer ATLI
fuente
Pero esto busca en el PATH completo si program.exeexiste, no solo en una carpeta
jeb
-1

Use el comando: powershell Test-Path "exe que está buscando"

Devolverá True si está presente; de ​​lo contrario, False.

Akkidukes
fuente
Esto no funcionará. Test-Pathsolo verifica la ruta especificada, es decir Test-Path nuget.exe, devolverá verdadero solo si nuget.exeestá en el directorio actual. Si nuget.exe no está en el directorio actual, devolverá falso, incluso si está en un directorio listado en la variable PATH. En PowerShell Get-Commandpodría funcionar mejor ( stackoverflow.com/questions/11242368/… ), pero tenga en cuenta que para PowerShell el directorio actual no está en la ruta.
Ronald Zarīts
1
Como señaló @RonaldZarits, para obtener soporte completo de PowerShell, puede usar Get-Command con dos opciones. Primero proporcione la ubicación del directorio actual, luego dé solo el nombre del exe. (Get-Command ".\notepad", "notepad" -ErrorAction Ignore -CommandType Application) -ne $nulldevolverá verdadero si se encuentra local o en la ruta.
John C
-1

Para aquellos que buscan una opción de PowerShell. Puede usar el Get-Commandcmdlet pasando dos elementos. Primero proporcione la ubicación del directorio actual con el .\prefijo, luego proporcione solo el nombre del exe.

(Get-Command ".\notepad", "notepad" -ErrorAction Ignore -CommandType Application) -ne $null

Eso devolverá verdadero si se encuentra localmente o en rutas de todo el sistema.

Juan C
fuente
Nada mejor que votar negativamente y ejecutar usuarios. Si no está de acuerdo y va a llegar a votar negativamente, agregue también un comentario para explicar la razón por la que no está de acuerdo en que este no es un buen enfoque para obtener los resultados deseados.
John C