- Is there an equivalent of ‘which’ on the Windows command line?
- 26 Answers 26
- Finding executables using only part of the name
- Finding custom executables
- Команды type, which, whereis, whatis и locate
- Команда type
- Команда which
- Команда whereis
- Команда whatis
- Команда locate
- A whereis utility
- Using whereis
- Using LoadLibraryEx to load images
- The App Paths
- Building the project
- Supplement: Why is this better than the traditional whereis command implementation?
- My whereis utility
- The classic «let’s pretend» code
- WHERE.exe
Is there an equivalent of ‘which’ on the Windows command line?
As I sometimes have path problems, where one of my own cmd scripts is hidden (shadowed) by another program (earlier on the path), I would like to be able to find the full path to a program on the Windows command line, given just its name.
Is there an equivalent to the UNIX command ‘which’?
On UNIX, which command prints the full path of the given command to easily find and repair these shadowing problems.
26 Answers 26
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:
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:
It actually returns all possibilities but you can tweak it quite easily for specific search rules.
$PATH:%i To add it to an alias.bat script that you load everytime you run cmd.exe (put the above script in a new directory called C:\usr\aliases): DOSKEY which=C:\usr\aliases\which.bat $* Then you can make a script to launch cmd.exe with the alias.bat file: cmd.exe /K E:\usr\aliases\alias.bat – Brad T. Apr 25 ’14 at 20:42
Under PowerShell, Get-Command will find executables anywhere in $Env:PATH .
And since powershell let’s you define aliases, which can be defined like so.
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
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.
See Get-Command for more options and examples.
In Windows PowerShell:
If you have PowerShell installed (which I recommend), you can use the following command as a rough equivalent (substitute programName for your executable’s name):
The GnuWin32 tools have which , along with a whole slew of other Unix tools.
In Windows CMD which calls where :
Cygwin is a solution. If you don’t mind using a third-party solution, then Cygwin is the way to go.
Cygwin gives you the comfort of *nix in the Windows environment (and you can use it in your Windows command shell, or use a *nix shell of your choice). It gives you a whole host of *nix commands (like which ) for Windows, and you can just include that directory in your PATH .
In PowerShell, it is gcm , which gives formatted information about other commands. If you want to retrieve only path to executable, use .Source .
For instance: gcm git or (gcm git).Source
- Available for Windows XP.
- Available since PowerShell 1.0.
- gcm is an alias of Get-Command cmdlet.
- Without any parameters, it lists down all the available commands offered by the host shell.
- You can create a custom alias with Set-Alias which gcm and use it like: (which git).Source .
- Official docs: https://technet.microsoft.com/en-us/library/ee176842.aspx
I have a function in my PowerShell profile named ‘which’
Here’s what the output looks like:
gold on windows platforms, puts all the nice unix utilities on a standard windows DOS. Been using it for years.
It has a ‘which’ included. Note that it’s case sensitive though.
NB: to install it explode the zip somewhere and add . \UnxUtils\usr\local\wbin\ to your system path env variable.
If you can find a free Pascal compiler, you can compile this. At least it works and shows the algorithm necessary.
Not in stock Windows but it is provided by Services for Unix and there are several simple batch scripts floating around that accomplish the same thing such this this one.
The best version of this I’ve found on Windows is Joseph Newcomer’s «whereis» utility, which is available (with source) from his site.
The article about the development of «whereis» is worth reading.
None of the Win32 ports of Unix which that I could find on the Internet are satistactory, because they all have one or more of these shortcomings:
- No support for Windows PATHEXT variable. (Which defines the list of extensions implicitely added to each command before scanning the path, and in which order.) (I use a lot of tcl scripts, and no publicly available which tool could find them.)
- No support for cmd.exe code pages, which makes them display paths with non-ascii characters incorrectly. (I’m very sensitive to that, with the ç in my first name :-))
- No support for the distinct search rules in cmd.exe and the PowerShell command line. (No publicly available tool will find .ps1 scripts in a PowerShell window, but not in a cmd window!)
So I eventually wrote my own which, that suports all the above correctly.
Команды type, which, whereis, whatis и locate
Команда type
Команда type позволяет выяснить, содержится ли некоторая команда в системе, и определить тип данной команды. Команда также сообщает, является ли название команды действительным и где именно в системе находится эта команда:
Команда which
Команда which выводит полный путь до команды, если она находится в пути поиска $PATH . Команда which показывает первую найденную команду в переменной $PATH . Если надо проверить существование нескольких совпадений, используется опция -a :
Команда whereis
Команда whereis позволяет найти не только исполняемые файлы, но и файлы документации и конфигурации. Выполняет поиск в ограниченном количестве каталогов, например в каталогах стандартных двоичных файлов, каталогах библиотек и в каталогах man .
Команда whatis
Команда whatis показывает краткую информацию о команде из ее man-страницы.
Команда locate
Команда locate выполняет поиск по базе данных имен файлов, хранящейся в Linux. Для получения актуальных результатов, необходимо регулярно обновлять базу данных со списком имен файлов. Чаще всего ОС настроена таким образом, что обновление будет выполняться автоматически. Если обновление по умолчанию отключено, можно обновить базу данных вручную:
- -q — позволяет скрыть сообщения об ошибках (например, нет доступа к файлу)
- -n — позволяет ограничить количество возвращаемых результатов
- -c — позволяет узнать количество файлов, соответствующих заданному критерию поиска
- -i — позволяет провести поиск файлов без учета регистра
A whereis utility
This is a little utility that emulates the Unix whereis command. Given the name of an executable, it will display the full path to the executable image. However, in the case of Windows, there are several kinds of executable images, such as DLLs, ActiceX controls, even device drivers. This little utility can find all of them.
Using whereis
If no parameter is supplied, the usual «usage» box is displayed
Note the two options that can be supplied.
Copies the path to the clipboard, so it can be conveniently pasted to a target location |
Enables «critical errors» which will pop up a MessageBox if one of these errors is detected. The most common cause is a file which is not a valid executable file. |
If a name without an extension is provided, an attempt is made to look up various extensions
The order of search, an explicit extension is not provided, is
.exe | Executable file (application) |
.dll | Dynamic Link Library |
.ocx | ActiveX control |
.sys | Device Driver |
.com | 16-bit MS-DOS executable |
Unlike the normal whereis utility that simulates the lookup algorithm, this uses whatever lookup algorithm is current on the current platform. Different releases of Windows, and different service packs, have different search paths implemented. Trying to keep updating the program by looking at the service pack level and hoping the simulation is correct seems to be a losing methodology. So I decided to use the built-in Windows mechanisms for doing this.
This program is an outgrowth of my work on another project, the LoadLlibrary Explorer, which is still under construction.
Using LoadLibraryEx to load images
The methodology here is to use LoadLibraryEx to load the executable image. This will also load executable file images. To avoid second-order effects caused by not having required DLLs in the search path, the DONT_RESOLVE_DLL_REFERENCES flag is specified. This will load the executable but will not attempt to resolve any import records on the executable image.
Having loaded the module, which is loaded using whatever the load resolution algorithm is on the current platform, the program then executes a GetModuleFileName on the handle returned. The result is then printed.
The App Paths
When ShellExecute or ShellExecuteEx are called, two Registry keys come into play. If a program is launched by an application calling ShellExecute(Ex), and the module name is not qualified by a full path, the registry key based on the filename is used. So if there is an attempt to launch filename.exe and the key is specified as
comes into play. The (Default) value for this key gives the path to the executable image. If this is present, it is used as the actual launch path.
If the Path variable is present, it represents a PATH string value which is appended to the end of the current PATH value, and this is used as the PATH for the execution of the process. This can change the search path for DLLs, and this path is not taken into account by the whereis program. However, if whereis finds a key that matches the executable name (only if the argument has either no extension, or has a .exe extension), it will print out the (Default) value of the key, and the Path value of the key. For example
Note that there are many possible key values under the indicated key. ShellExecute(Ex) is primarily concerned with the (Default) and Path values; note that whereis does not account for these when determining the location of an executable or where a DLL is loaded from.
The command shell ( cmd.exe ) does not use ShellExecute to launch a program.
Building the project
This project builds Release and Debug versions for both 8-bit (ANSI) apps and Unicode apps, and works in both VS6 and VS.NET. The executables for VS.NET go into directories with suffix «7», e.g., Debug7 or Unicode Release7 .
Supplement: Why is this better than the traditional whereis command implementation?
I got a post where someone posted the usual let’s-simulate-what-we-think-the-path-is code and said «Why isn’t this good enough?» The person posted the complete source code. Note the difference in these two examples.
My whereis utility
The classic «let’s pretend» code
I copied the code posted, called it a project badwhereis, built it, and ran it:. Note that it does not properly account for the «known DLLs» feature. It erroneously claims that the kernel32.dll file would be loaded from the local directory, but LoadLibrary(Ex) in fact does not load it from that directory! Read about the various search paths LoadLibrary uses, under what settings, with what releases of Windows, under which service packs, and this shows that relying upon simulation of the behavior of LoadLibrary(Ex) has to be precise, knowing which platform, which service pack, which Registry settings apply, etc. I rest my case. Simulation is not sufficient; you have to rely on what the kernel call does in your environment.
See what I mean about bad simulations?
The views expressed in these essays are those of the author, and in no way represent, nor are they endorsed by, Microsoft.
WHERE.exe
Locate and display files in a directory tree.
The WHERE command is roughly equivalent to the UNIX ‘which’ command. By default, the search is done in the current directory and in the PATH.
The WHERE command can either perform a recursive search within one directory ( /R ) or search through a list of folders ( Path;Path: ), but not both.
By default, WHERE searches the current directory and the paths specified in the PATH environment variable.
The WHERE command is particularly useful to reveal multiple versions of the same comand/script/utility on the system PATH.
WHERE will use the PATHEXT variable to include all executable files, so WHERE robocopy will find the location of robocopy.exe
This PATHEXT expansion applies even if you are not searching for an executable. For instance, the command WHERE monday.csv will list the file monday.csv in the current directory, as expected, but this will also list files like monday.csv.exe , monday.csv.com should they exist. To avoid this behaviour, clear the PATHEXT variable temporarily with Set «PATHEXT=»
To run the WHERE command from PowerShell it is necessary to give the full path C:\Windows\System32\WHERE.exe otherwise the Where-Object cmdlet will take precedence.
Find all copies of robocopy.exe in the current system path:
Find all files named ‘Zappa’ on the remote computer ‘Server64’ searching the subdirectories of Share1:
WHERE /r \\Server64\Share1 Zappa.*
List all the .CSV files on both the work and play folders:
“Who never walks, save where he sees men’s tracks, makes no discoveries”