2012-06-13 13 views
29

Ich möchte herausfinden, welche Version einer ausführbaren Datei die CMD-Shell verwendet. In jeder Unix-Shell würde ich which verwenden, um es zu finden.Was ist das Cmd/Powershell-Äquivalent von `which` auf bash?

Gibt es einen entsprechenden Befehl in einer der Windows-Shells?

+0

Ja, es gibt http://StackOverflow.com/Questions/304319/is-there-an-equivalent-of-which-on-windows/304441#304441 – paxdiablo

Antwort

50

Verschiedene.

  1. where ist eine direkte Entsprechung:

    C:\Users\Joey>where cmd 
    C:\Windows\System32\cmd.exe 
    

    Beachten Sie, dass in Powershell where selbst ein Alias ​​für Where-Object ist, so dass Sie where.exe in Powershell verwenden müssen.

  2. In cmd können Sie auch for verwenden:

    C:\Users\Joey>for %x in (powershell.exe) do @echo %~$PATH:x 
    C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe 
    
  3. In Powershell haben Sie Get-Command und seine alias gcm die das gleiche tut, wenn Sie ein Argument übergeben (funktioniert aber auch für Aliase, Cmdlets und Funktionen in PowerShell):

    PS C:\Users\Joey> Get-Command where 
    
    CommandType  Name   Definition 
    -----------  ----   ---------- 
    Alias   where   Where-Object 
    Application  where.exe  C:\Windows\system32\where.exe 
    

    Der erste zurückgegebene Befehl ist derjenige, der ausgeführt werden würde.

+1

Aus irgendeinem Grund, 'where' hat nicht funktioniert für mich überhaupt (nichts gedruckt und sofort beendet), aber 'gcm' hat super funktioniert. – Hassan

+1

@Hassan: Wie Sie aus der Beispielausgabe von 'Get-Command where' auf der PowerShell entnehmen können, ist' where' eigentlich ein Alias ​​für 'Where-Object', der Vorrang vor' wher.exe' hat. Um 'where.exe' auszuführen, müssen Sie' wher.exe' eingeben. Zumindest in der PowerShell. – Joey

+0

Oh. Ja das war das Problem. Vielen Dank! – Hassan

4

Der WHERE Befehl ist nicht ganz dasselbe wie Unix which, weil es alle passenden Dateien im aktuellen Verzeichnis oder PATH aufgelistet sind. Wie Joey sagt, ist der Erste, der aufgeführt wird, der, der ausführt. Es ist einfach, ein Batch-Skript zu erstellen, das nur das erste gefundene Skript zurückgibt.

@echo off 
for /f "delims=" %%F in ('where %1') do (
    echo %%F 
    exit /b 
) 

Aber WHERE ist relativ langsam.

Unten ist ein WHICH.BAT Skript, das schneller ist und ein bisschen mehr tut. Es verwendet umfangreiche verzögerte Expansions-Toggelung, weil: 1)% PATH% erweitern ist unzuverlässig, wenn es nicht aufgezählte Sonderzeichen gibt. 2) Durch das Erweitern von FOR-Variablen bei aktivierter verzögerter Erweiterung werden Werte korrumpiert, die ! enthalten.

::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 

UPDATE

ich deutlich das Skript ändern musste oben, weil es als externes einen internen Befehl falsch Auflistung, wenn es in der PATH eine exe-Datei mit dem gleichen Stammnamen irgendwo zufällig existieren.