Je voudrais savoir quelle version d'un exécutable le CMD Shell utilise. Dans n'importe quel shell Unix, j'utiliserais which
pour le trouver.
Existe-t-il une commande équivalente dans l'un des shells Windows?
Divers.
where
est un équivalent direct:
C:\Users\Joey>where cmd
C:\Windows\System32\cmd.exe
Notez que dans PowerShell where
lui-même est un alias pour Where-Object
, vous devez donc utiliser where.exe
dans PowerShell.
Dans cmd
, vous pouvez également utiliser for
:
C:\Users\Joey>for %x in (powershell.exe) do @echo %~$PATH:x
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
Dans PowerShell, vous avez Get-Command
et son alias gcm
qui fait de même si vous passez un argument (mais fonctionne également pour les alias, les applets de commande et les fonctions dans PowerShell):
PS C:\Users\Joey> Get-Command where
CommandType Name Definition
----------- ---- ----------
Alias where Where-Object
Application where.exe C:\Windows\system32\where.exe
La première commande renvoyée est celle qui serait exécutée.
La commande WHERE
n'est pas tout à fait la même chose qu'unix which
car elle répertorie tous les fichiers correspondants trouvés dans le répertoire courant ou PATH. Comme le dit Joey, le premier répertorié est celui qui exécute. Il est simple de créer un script batch qui ne renverra que le premier trouvé.
@echo off
for /f "delims=" %%F in ('where %1') do (
echo %%F
exit /b
)
Mais WHERE
est relativement lent.
Voici un script WHICH.BAT qui est plus rapide et en fait un peu plus. Il utilise un basculement d'expansion retardé étendu car: 1) L'expansion de% PATH% n'est pas fiable s'il y a des caractères spéciaux non cités. 2) L'expansion des variables FOR pendant que l'expansion retardée est activée corrompt les valeurs qui contiennent !
.
::WHICH.BAT CommandName [ReturnVar]
::
:: Determines the full path of the file that would execute if
:: CommandName were executed.
::
:: The result is stored in variable ReturnVar, or else it is
:: echoed to stdout if ReturnVar is not specified.
::
:: If no file is found, then an error message is echoed to stderr.
::
:: The ERRORLEVEL is set to one of the following values
:: 0 - Success: A matching file was found
:: 1 - CommandName is an internal command
:: 2 - No file was found and CommandName is not an internal command
:: 3 - Improper syntax - no CommandName specified
::
@echo off
setlocal disableDelayedExpansion
set "file=%~1"
setlocal enableDelayedExpansion
if not defined file (
>&2 echo Syntax error: No CommandName specified
exit /b 3
)
:: test for internal command
echo(!file!|findstr /i "[^abcdefghijklmnopqrstuvwxyz]" >nul || (
set "empty=!temp!\emptyFolder"
md "!empty!" 2>nul
del /q "!empty!\*" 2>nul >nul
setlocal
pushd "!empty!"
set path=
(call )
!file! /? >nul 2>nul
if not errorlevel 9009 (
>&2 echo "!file!" is an internal command
popd
exit /b 1
)
popd
endlocal
)
:: test for external command
set "noExt="
if "%~x1" neq "" if "!PATHEXT:%~x1=!" neq "!PATHEXT!" set noExt="";
set "modpath=.\;!PATH!"
@for %%E in (%noExt%%PATHEXT%) do @for %%F in ("!file!%%~E") do (
setlocal disableDelayedExpansion
if not "%%~$modpath:F"=="" if not exist "%%~$modpath:F\" (
endlocal & endlocal & endlocal
if "%~2"=="" (echo %%~$modpath:F) else set "%~2=%%~$modpath:F"
exit /b 0
)
endlocal
)
endlocal
>&2 echo "%~1" is not a valid command
exit /b 2
MISE À JOUR
J'ai dû modifier de manière significative le script ci-dessus car il listait incorrectement une commande interne comme externe s'il existait un fichier exe avec le même nom racine quelque part dans le CHEMIN.