Is there an equivalent of 'which' on the Windows command line? [closed]
Windows Server 2003 and later (i.e. anything after Windows XP 32 bit) provide the where.exe
program which does some of what which
does, though it matches all types of files, not just executable commands. (It does not match built-in shell commands like cd
.) It will even accept wildcards, so where nt*
finds all files in your %PATH%
and current directory whose names start with nt
.
Try where /?
for help.
Note that Windows PowerShell defines where
as an alias for the Where-Object
cmdlet, so if you want where.exe
, you need to type the full name instead of omitting the .exe
extension.
While later versions of Windows have a where
command, you can also do this with Windows XP by using the environment variable modifiers, as follows:
c:\> for %i in (cmd.exe) do @echo. %~$PATH:i C:\WINDOWS\system32\cmd.exec:\> for %i in (python.exe) do @echo. %~$PATH:i C:\Python25\python.exe
You don't need any extra tools and it's not limited to PATH
since you can substitute any environment variable (in the path format, of course) that you wish to use.
And, if you want one that can handle all the extensions in PATHEXT (as Windows itself does), this one does the trick:
@echo offsetlocal enableextensions enabledelayedexpansion:: Needs an argument.if "x%1"=="x" ( echo Usage: which ^<progName^> goto :end):: First try the unadorned filenmame.set fullspec=call :find_it %1:: Then try all adorned filenames in order.set mypathext=!pathext!:loop1 :: Stop if found or out of extensions. if "x!mypathext!"=="x" goto :loop1end :: Get the next extension and try it. for /f "delims=;" %%j in ("!mypathext!") do set myext=%%j call :find_it %1!myext!:: Remove the extension (not overly efficient but it works).:loop2 if not "x!myext!"=="x" ( set myext=!myext:~1! set mypathext=!mypathext:~1! goto :loop2 ) if not "x!mypathext!"=="x" set mypathext=!mypathext:~1! goto :loop1:loop1end:endendlocalgoto :eof:: Function to find and print a file in the path.:find_it for %%i in (%1) do set fullspec=%%~$PATH:i if not "x!fullspec!"=="x" @echo. !fullspec! goto :eof
It actually returns all possibilities but you can tweak it quite easily for specific search rules.
Under PowerShell, Get-Command
will find executables anywhere in $Env:PATH
.
$ Get-Command eventvwrCommandType Name Definition----------- ---- ----------Application eventvwr.exe c:\windows\system32\eventvwr.exeApplication eventvwr.msc c:\windows\system32\eventvwr.msc
And since powershell let's you define aliases, which
can be defined like so.
$ sal which gcm # short form of `Set-Alias which Get-Command`$ which foo...
PowerShell commands are not just executable files (.exe
, .ps1
, etc). They can also be cmdlets, functions, aliases, custom executable suffixes set in $Env:PATHEXT
, etc. Get-Command
is able to find and list all of these commands (quite akin to Bash's type -a foo
). This alone makes it better than where.exe
, which.exe
, etc which are typically limited to finding just executables.
Finding executables using only part of the name
$ gcm *disk*CommandType Name Version Source----------- ---- ------- ------Alias Disable-PhysicalDiskIndication 2.0.0.0 StorageAlias Enable-PhysicalDiskIndication 2.0.0.0 StorageFunction Add-PhysicalDisk 2.0.0.0 StorageFunction Add-VirtualDiskToMaskingSet 2.0.0.0 StorageFunction Clear-Disk 2.0.0.0 StorageCmdlet Get-PmemDisk 1.0.0.0 PersistentMemoryCmdlet New-PmemDisk 1.0.0.0 PersistentMemoryCmdlet Remove-PmemDisk 1.0.0.0 PersistentMemoryApplication diskmgmt.msc 0.0.0.0 C:\WINDOWS\system32\diskmgmt.mscApplication diskpart.exe 10.0.17... C:\WINDOWS\system32\diskpart.exeApplication diskperf.exe 10.0.17... C:\WINDOWS\system32\diskperf.exeApplication diskraid.exe 10.0.17... C:\WINDOWS\system32\diskraid.exe...
Finding custom executables
Unlike UNIX, where executables are files with the executable (+x
) bit set, executables on windows are files present in one of the directories specified in the $PATH
env. variable whose filename suffixes are named in the $PATHEXT
env. variable (defaults to .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.CPL
).
As Get-Command
also honours this env. variable, it can be extended to list custom executables. e.g.
$ $Env:PATHEXT="$Env:PATHEXT;.dll;.ps1;.psm1;.py" # temporary assignment, only for this shell's process$ gcm user32,kernel32,*WASM*,*http*pyCommandType Name Version Source----------- ---- ------- ------ExternalScript Invoke-WASMProfiler.ps1 C:\WINDOWS\System32\WindowsPowerShell\v1.0\Invoke-WASMProfiler.ps1Application http-server.py 0.0.0.0 C:\Users\ME\AppData\Local\Microsoft\WindowsApps\http-server.pyApplication kernel32.dll 10.0.17... C:\WINDOWS\system32\kernel32.dllApplication user32.dll 10.0.17... C:\WINDOWS\system32\user32.dll
See Get-Command
for more options and examples.