analog - windows whereis command

Is there an equivalent of 'which' on the Windows command line? (15)

Dunno if this helps. Posted as answer because I don't know how to format code in comments (help?)

If you can find a free pascal compiler, you can compile this, or email me & I can try to dig one out, or mail back the exe or post it somewhere. I post the code, bad as it is, because at least it works & shows the algorithm necessary.

program Whence (input,output);
  Uses Dos, my_funk;
  Const program_version = '1.00';
        program_date    = '17 March 1994';
  VAR   path_str          : string;
        command_name      : NameStr;
        command_extension : ExtStr;
        command_directory : DirStr;
        search_dir        : DirStr;
        result            : DirStr;

  procedure Check_for (file_name : string);
    { check existance of the passed parameter. If exists, then state so   }
    { and exit.                                                           }
    if Fsearch(file_name,'') <> '' then
      WriteLn('Dos command = ',Fexpand(file_name));
      Halt(0);    { structured ? whaddayamean structured ? }

  function Get_next_dir : DirStr;
    { Returns the next directory from the path variable, truncating the   }
    { variable every time. Implicit input (but not passed as parameter)   }
    { is, therefore, path_str                                             }
    var  semic_pos  : Byte;

      semic_pos  := Pos(';',path_str);
      if (semic_pos = 0) then
        Get_next_dir := '';

      result       := Copy(Path_str,1,(semic_pos - 1));  { return result   }
      { hmm! although *I* never reference a Root drive (my directory tree) }
      { is 1/2 way structured), some network logon software which I run    }
      { does (it adds Z:\ to the path). This means that I have to allow    }
      { path entries with & without a terminating backslash. I'll delete   }
      { anysuch here since I always add one in the main program below.     }
      if (Copy(result,(Length(result)),1) = '\') then

      path_str     := Copy(path_str,(semic_pos + 1),
                                 (length(path_str) - semic_pos));
      Get_next_dir := result;
  end;  { of function get_next_dir }

  { the following is a kludge which makes the function Get_next_dir easier  }
  { to implement. By appending a semi-colon to the end of the path         }
  { Get_next_dir doesn't need to handle the special case of the last entry }
  { which normally doesn't have a semic afterwards. It may be a kludge,    }
  { but it's a documented kludge (you might even call it a refinement).    }
  path_str := GetEnv('Path') + ';';

  if (paramCount = 0) then
    WriteLn('Whence : V',program_version,' from ',program_date);
    WriteLn('Usage  : WHENCE command[.extension]');
    WriteLn('Whence is a ''find file''type utility witha difference');
    Writeln('There are are already more than enough of those   :-)');
    Write  ('Use Whence when you''re not sure where a command which you ');
    WriteLn('want to invoke');
    WriteLn('actually resides.');
    Write  ('If you intend to invoke the command with an extension e.g ');
    Writeln('"my_cmd.exe param"');
    Write  ('then invoke Whence with the same extension e.g ');
    WriteLn('"Whence my_cmd.exe"');
    Write  ('otherwise a simple "Whence my_cmd" will suffice; Whence will ');
    Write  ('then search the current directory and each directory in the ');
    Write  ('for, then My_cmd.exe and lastly for my_cmd.bat, ');
    Write  ('just as DOS does');

  if (command_directory <> '') then
WriteLn('directory detected *',command_directory,'*');

  if (command_extension <> '') then
    path_str := Fsearch(paramstr(1),'');    { current directory }
    if   (path_str <> '') then WriteLn('Dos command = "',Fexpand(path_str),'"')
      path_str := Fsearch(paramstr(1),GetEnv('path'));
      if (path_str <> '') then WriteLn('Dos command = "',Fexpand(path_str),'"')
                          else Writeln('command not found in path.');
    { O.K, the way it works, DOS looks for a command firstly in the current  }
    { directory, then in each directory in the Path. If no extension is      }
    { given and several commands of the same name exist, then .COM has       }
    { priority over .EXE, has priority over .BAT                             }

    Check_for(paramstr(1) + '.com');     { won't return if file is found }
    Check_for(paramstr(1) + '.exe');
    Check_for(paramstr(1) + '.bat');

    { not in current directory, search thru path .... }

    search_dir := Get_next_dir;

    while (search_dir <> '') do
       Check_for(search_dir + '\' + paramstr(1) + '.com');
       Check_for(search_dir + '\' + paramstr(1) + '.exe');
       Check_for(search_dir + '\' + paramstr(1) + '.bat');
       search_dir := Get_next_dir;

    WriteLn('DOS command not found : ',paramstr(1));

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.

For you XP users (which have no where command built-in), I have written a "where like" command as a rubygem called whichr

To install it, install ruby


gem install whichr

run it like

c:\>whichr cmd_here

I am using GOW(Gnu on Windows) which is a light version of cygwin. You can grap it from github here.

Gow (Gnu On Windows) is the lightweight alternative to Cygwin. It uses a convenient Windows installer that installs about 130 extremely useful open source UNIX applications compiled as native win32 binaries. It is designed to be as small as possible, about 10 MB, as opposed to Cygwin which can run well over 100 MB depending upon options. - About Description(Brent R. Matzelle)

Screenshot of a list of commands included in GOW.

I have a function in my PowerShell profile named 'which'

function which {
    get-command $args[0]| format-list

Here's what the output looks like:

PS C:\Users\fez> which python

Name            : python.exe
CommandType     : Application
Definition      : C:\Python27\python.exe
Extension       : .exe
Path            : C:\Python27\python.exe
FileVersionInfo : File:             C:\Python27\python.exe
                  Debug:            False
                  Patched:          False
                  PreRelease:       False
                  PrivateBuild:     False
                  SpecialBuild:     False

I have used the which module from npm for quite a while, and it works very well: It is a great multi platform alternative.

Now I switched to the which that comes with Git. Just add to your path the /usr/bin path from Git, which is usually at C:\Program Files\Git\usr\bin\which.exe. The which binary will be at C:\Program Files\Git\usr\bin\which.exe. It is faster and also works as expected.

In Windows CMD which calls where:

$ where php
C:\Program Files\PHP\php.exe

In windows powershell:

set-alias which where.exe

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.

Surprised that nobody has mentioned cygwin as a solution yet. If you don't mind using a 3rd-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.

The GnuWin32 tools have which, along with a whole slew of other Unix tools.

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.

Under PowerShell get-command will find executables anywhere in $Env:PATH.

get-command eventvwr

CommandType   Name          Definition
-----------   ----          ----------
Application   eventvwr.exe  c:\windows\system32\eventvwr.exe
Application   eventvwr.msc  c:\windows\system32\eventvwr.msc

It also finds powershell cmdlets, functions, aliases, files with custom executables extensions via $Env:PATHEXT, etc defined for the current shell (quite akin to bash's type -a foo) - making it a better go-to than other tools like where.exe, which.exe, etc which are unaware of these PowerShell commands.

You can quickly set up an alias with sal which gcm (short form of set-alias which get-command).

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:\> for %i in (python.exe) do @echo.   %~$PATH:i

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 off
setlocal 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!
    :: 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).

    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

goto :eof

:: Function to find and print a file in the path.

    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.