在Windows命令行上是否有等效的”which”?

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

由于我有时会遇到路径问题,我自己的一个命令脚本被另一个程序(在路径的前面)隐藏(隐藏),所以我希望能够在Windows命令行上找到程序的完整路径,只给出它的名称。

是否有与unix命令"which"等效的命令?

在UNIX上,which command打印给定命令的完整路径,以便轻松查找和修复这些阴影问题。


Windows Server 2003及更高版本(即Windows XP 32位之后的任何版本)提供了where.exe程序,它执行which所做的某些操作,尽管它匹配所有类型的文件,而不仅仅是可执行命令。(它与诸如cd这样的内置shell命令不匹配)它甚至会接受通配符,因此where nt*会查找%PATH%和当前目录中名称以nt开头的所有文件。

尝试使用where /?寻求帮助。

请注意,Windows PowerShell将where定义为Where-ObjectCmdlet的别名,因此,如果要where.exe的话,需要键入全名,而不是省略.exe扩展名。


虽然较新版本的Windows有一个where命令,但您也可以使用环境变量修饰符对Windows XP执行此操作,如下所示:

1
2
3
4
5
c:\> for %i in (cmd.exe) do @echo.   %~$PATH:i
   C:\WINDOWS\system32\cmd.exe

c:\> for %i in (python.exe) do @echo.   %~$PATH:i
   C:\Python25\python.exe

您不需要任何额外的工具,而且它不限于PATH,因为您可以替换任何您想要使用的环境变量(当然是路径格式)。

而且,如果您想要一个可以处理PathExt中所有扩展的扩展(就像Windows本身一样),这个可以做到:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
@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!
: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

:end
endlocal
goto :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

它实际上返回所有的可能性,但您可以很容易地为特定的搜索规则调整它。


在Powershell下,Get-CommandWill find executable anywhere in $Env:PATH

1
2
3
4
5
6
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 executible extensions via EDOCX1[…]2,.defined for the current shell(quite Akin Akin to Bash's EDOCX1[…]3)-making it a better go-to than other tools like EDOCX1[…],edoc1[…]5,]which are a war of these powers com

仅以名称的一部分找到可执行的ZZU1可执行的定制

找到其他可执行的非窗口(Python、红宝石、珍珠等),文件扩展到那些可执行的需要添加到PATHEXT的环境变量(Defaults to .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.CPL以识别这些PATH延伸的文件。同样,这一变量也可以扩展到列举可执行的习惯。E.G.

1
2
3
4
5
6
7
8
9
10
$Env:PATHEXT="$Env:PATHEXT;.dll;.ps1;.psm1;.py"     # temporary assignment, only for this shell's process

gcm user32,kernel32,*WASM*,*http*py

CommandType     Name                        Version    Source
-----------     ----                        -------    ------
ExternalScript  Invoke-WASMProfiler.ps1                C:\WINDOWS\System32\WindowsPowerShell\v1.0\Invoke-WASMProfiler.ps1
Application     http-server.py              0.0.0.0    C:\Users\ME\AppData\Local\Microsoft\WindowsApps\http-server.py
Application     kernel32.dll                10.0.17... C:\WINDOWS\system32\kernel32.dll
Application     user32.dll                  10.0.17... C:\WINDOWS\system32\user32.dll

你可以用sal which gcm(EDOCX1〕〔11〕的简短形式迅速地建立一个别名。

更多的信息和实例可在在线帮助下找到。


在Windows PowerShell中:

1
set-alias which where.exe


如果安装了PowerShell(我建议),则可以使用以下命令作为大致等效命令(将programname替换为可执行文件的名称):

1
($Env:Path).Split(";") | Get-ChildItem -filter programName*

更多的是:我的Manwich!PowerShell,其中


gnuwin32工具有which,以及大量其他unix工具。


In windows cmd whichcalls where

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

Cygwin是一个解决方案。如果您不介意使用第三方解决方案,那么Cygwin就是解决方案。

Cygwin在Windows环境中为您提供了*nix的舒适性(您可以在Windows命令shell中使用它,也可以选择使用*nix shell)。它为Windows提供了一整套*nix命令(如which),您只需将该目录包含在PATH中即可。


在Powershell,IT is gcm,which gives formated information about other commands.如果你想检索唯一可执行的路径,请使用.Source

For instance:gcm gitor (gcm git).Source

Tidbits:

  • Available for Windows XP.
  • Available since Powershell 1.0.
  • 这是一个别名
  • 没有任何参数,它列表了主机壳发出的所有可用命令。
  • 你可以用Set-Alias which gcm创建一个特殊的别名,并使用它:(which git).Source
  • Official docs:https http://technet.microsoft.com/en-us/library/e176842.aspx


我在我的电力地形中有一个功能

1
2
3
function which {
    get-command $args[0]| format-list
}

这里的输出外观像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
                  InternalName:
                  OriginalFilename:
                  FileVersion:
                  FileDescription:
                  Product:
                  ProductVersion:
                  Debug:            False
                  Patched:          False
                  PreRelease:       False
                  PrivateBuild:     False
                  SpecialBuild:     False
                  Language:


从这里获取unxutils:http://sourceforge.net/projects/unxutils/

Windows平台上的黄金,将所有优秀的Unix实用程序放在标准的Windows DOS上。多年来一直在使用它。

它包括一个"which"。注意,它是区分大小写的。

注意:要安装它,请将zip分解到某个位置并将其添加到系统路径env变量中。


如果你能找到一个免费的帕斯卡编译器,你可以编译它。至少它可以工作并显示出必要的算法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
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 existence of the passed parameter. If exists, then state so   }
    { and exit.                                                           }
  begin
    if Fsearch(file_name, '') <> '' then
    begin
      WriteLn('DOS command = ', Fexpand(file_name));
      Halt(0);    { structured ? whaddayamean structured ? }
    end;
  end;

  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;

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

      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
         Delete(result, Length(result), 1);

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

begin
  { 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
  begin
    WriteLn('Whence: V', program_version, ' from ', program_date);
    Writeln;
    WriteLn('Usage: WHENCE command[.extension]');
    WriteLn;
    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 My_cmd.com, then My_cmd.exe and lastly for my_cmd.bat, ');
    Write  ('just as DOS does');
    Halt(0);
  end;

  Fsplit(paramStr(1), command_directory, command_name, command_extension);
  if (command_directory <> '') then
  begin
WriteLn('directory detected *', command_directory, '*');
    Halt(0);
  end;

  if (command_extension <> '') then
  begin
    path_str := Fsearch(paramstr(1), '');    { Current directory }
    if   (path_str <> '') then WriteLn('Dos command ="', Fexpand(path_str), '"')
    else
    begin
      path_str := Fsearch(paramstr(1), GetEnv('path'));
      if (path_str <> '') then WriteLn('Dos command ="', Fexpand(path_str), '"')
                          else Writeln('command not found in path.');
    end;
  end
  else
  begin
    { 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 through path ... }

    search_dir := Get_next_dir;

    while (search_dir <> '') do
    begin
       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;
    end;

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


我在Windows上找到的最好版本是Joseph Newcomer的"Wheris"实用程序,它可以从他的站点(带有源代码)获得。

关于"何处"发展的文章值得一读。


不是在普通窗口中,而是由Unix的服务提供的,有几个简单的批处理脚本在周围浮动,完成了与此相同的事情。


此分组文件使用CMD变量处理来确定将在路径中执行的命令。注:目前的目录总是在路径之前完成的,取决于API呼叫的其他位置在路径之前/之后正在寻找。

1
2
3
4
5
6
7
8
9
@echo off
echo.
echo PathFind - Finds the first file in in a path
echo ======== = ===== === ===== ==== == == = ====
echo.
echo Searching for %1 in %path%
echo.
set a=%~$PATH:1
If"%a%"=="" (Echo %1 not found) else (echo %1 found at %a%)

See set /?For help.


None of the Win32 Ports of UNIX which I could find on the Internet are satistactory,because they all have one or more of these shortcomings:

  • 无支持窗口路径变量。(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.)
  • 没有支持CMD.Exe Code pages,which makes them display paths with non-ASCII characters incorrectly.我对这个很敏感吗?在我的第一个名字:-)
  • 没有支持CMD.EXE和Powershell指挥线中的单独搜索规则。(PS1脚本将在一个Powershell Window中找到,但不在CMD Window!)

所以我可能写下自己的作品,那是正确的。

Available there:http://jf.larnoux.free.fr/progs/which.exe


我创建了类似于ned batchelder的工具:

正在路径中搜索.dll和.exe文件

虽然我的工具主要用于搜索各种DLL版本,但它显示了更多信息(日期、大小、版本),但它不使用pathext(我希望很快更新我的工具)。


你可以先安装GIT从下载GIT,然后打开GIT Bash and type:

1
which app-name

我使用的是视窗上的GNU(GNU),这是一个光亮的版本的Cygwin。你可以在这里抓住它。

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)

a screenshot of a list of commands included in gow:

MGX1〔0〕


TCC and TCC/L from JPSOFT are cmd.exe replaces that add significant functionality.这是TCC家庭指挥处理器的一个建筑物命令。


对于你的视窗用户(谁没有EDOCX1〕〔13〕),我写了一个像红宝石般的命令。

安装它,安装鲁比。

然后

1
gem install whichr

运行它。

c:>whichr cmd=uhere


我使用过NPM的which模块有一段时间了,效果很好:https://www.npmjs.com/package/which它是一个伟大的多平台选择。

现在我切换到Git附带的which。只需在您的路径中添加来自git的/usr/bin路径,它通常位于C:\Program Files\Git\usr\bin\which.exewhich二进制文件将位于C:\Program Files\Git\usr\bin\which.exe处。它速度更快,而且工作正常。