Windows命令行上是否有等同于“哪个”的内容?


2350

由于有时我会遇到路径问题,其中我自己的cmd脚本之一被另一个程序(位于路径的较早位置)隐藏(阴影),因此我希望能够在Windows命令行上找到程序的完整路径,如下所示只是它的名字。

是否有等效于UNIX命令“哪个”的命令?

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


3
Foredecker:如果在shell提示符下键入命令,“ which”将在PATH中搜索将运行的可执行文件。
Greg Hewgill

3
例如,如果您安装了5个Java版本,但您不知道使用了哪个Java版本,则可以键入“哪个Java”,它会为您提供二进制文件的路径
面向

9
MR说,@ Foredecker,它在Win2k3中是“哪里”,但Win2k3并不是问题的一部分。如果其他Windows版本中没有“ where”,则其他答案也有效。IMNSHO,适用于所有Windows版本的答案是最好的。另外,其他答案也不错,只是做事方式不同。
paxdiablo

36
我知道这个问题出现在SuperUser之前,但它可能属于那里。
palswim

16
which在标准Unix中没有命令。POSIX实用程序是type。C Shell具有which命令,并且某些系统将其作为外部可执行文件。例如,在Debian Linux上,which它来自一个名为的软件包debutils。此外部程序which无法“查看” shell内置,别名或功能。type做; Bash的type选项可以抑制这种情况,只需执行路径查找即可。
哈兹2015年

Answers:


2549

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

尝试where /?寻求帮助。

请注意,Windows PowerShell中定义where为一个别名Where-Objectcmdlet的,所以如果你想where.exe,你需要输入完整的名称,而不是省略的.exe扩展。


30
否,因为grep会检查其输入的内容,您必须明确给出该内容其中where.exe仅查看PATH环境变量中设置的一组目录中的文件
Michael Ratanapintha 2011年

12
@ Ajedi32 -正确的,是不是在XP。正如我所说的,“ Windows Server 2003及更高版本”。
Michael Ratanapintha 2012年

24
在Windows 8中工作
rob

57
请注意,除非您键入where.exe,否则它将无法在 Powershell中运行
JonnyRaa 2014年

17
请记住,where.exe不是一个shell内建命令,你必须%windir%\system32对你的%PATH%-这可能并非如此,因为使用where建议你可以在你的路径问题,是工作!
Tomasz Gandor 2015年

288

Windows的更高版本有where命令时,您也可以使用Windows XP通过使用环境变量修饰符来执行此命令,如下所示:

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一样),那么这个技巧就可以了:

@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

它实际上会返回所有可能性,但您可以针对特定的搜索规则轻松地对其进行调整。


7
嘿,我希望我已经学到了!不幸的是,它不适用于MS-DOS或Win9x(即,对于command.com)。(雷蒙德·陈(Raymond Chen)有一个更“精巧”的版本,您可以将其变成一个批处理文件:blogs.msdn.com/oldnewthing/archive/2005/01/20/357225.aspx
Michael Ratanapintha 09年

110
@Michael,如果您仍在使用DOS或Win95,则在路径上查找可执行文件是最小的问题:-)
paxdiablo

Windows可以将.exe识别为可执行文件。上次我which无意中在W95 / DOS天编写了一个后退代码,搜索顺序是-当前目录,然后是每个路径目录,分别是cmd.com,cmd.exe和cmd.bat,所以,即使是当前目录中的cmd.bat也是如此。执行路径之前的cmd.exe soemwhere
Mawg说恢复Monica 2010年

3
@mawg,原始文件用于您知道扩展名的地方,因为它会在UNIX下进行镜像(不会发生添加扩展名的诡计)。现在,我添加了一个可以执行您想要的操作的命令,但它不再是简单的命令,而是脚本。它首先尝试无修饰的命令,然后尝试每个扩展命令。希望能有所帮助。您可以根据自己的需要来调整它(例如,如果要与Windows使用相同的搜索顺序,则显示所有可能性)。
paxdiablo 2010年

2
要将其转换为批处理脚本,请创建一个名为“ that.bat”的文件:将该文件 @echo off for %%i in (%1) do @echo. %%~$PATH:%i 添加到每次运行cmd.exe时加载的alias.bat脚本中(将上述脚本放置在名为C:\ usr的新目录中\ aliases): DOSKEY which=C:\usr\aliases\which.bat $* 然后,您可以制作一个脚本以使用alias.bat文件启动cmd.exe: cmd.exe /K E:\usr\aliases\alias.bat
Brad T.

151

在PowerShell下,Get-Command将在中的任何位置找到可执行文件$Env:PATH

Get-Command eventvwr

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

它还发现PowerShell命令,函数,别名文件通过自定义的可执行文件的扩展$Env:PATHEXT等,为当前shell(相当类似于bash的定义type -a foo) -使之更好地去到比其他工具一样where.exewhich.exe等它不知道这些PowerShell命令。

仅使用名称的一部分查找可执行文件

gcm *disk*

CommandType     Name                             Version    Source
-----------     ----                             -------    ------
Alias           Disable-PhysicalDiskIndication   2.0.0.0    Storage
Alias           Enable-PhysicalDiskIndication    2.0.0.0    Storage
Function        Add-PhysicalDisk                 2.0.0.0    Storage
Function        Add-VirtualDiskToMaskingSet      2.0.0.0    Storage
Function        Clear-Disk                       2.0.0.0    Storage
Cmdlet          Get-PmemDisk                     1.0.0.0    PersistentMemory
Cmdlet          New-PmemDisk                     1.0.0.0    PersistentMemory
Cmdlet          Remove-PmemDisk                  1.0.0.0    PersistentMemory
Application     diskmgmt.msc                     0.0.0.0    C:\WINDOWS\system32\diskmgmt.msc
Application     diskpart.exe                     10.0.17... C:\WINDOWS\system32\diskpart.exe
Application     diskperf.exe                     10.0.17... C:\WINDOWS\system32\diskperf.exe
Application     diskraid.exe                     10.0.17... C:\WINDOWS\system32\diskraid.exe
...

查找自定义可执行文件

要查找其他非Windows可执行文件(python,ruby,perl等),需要将这些可执行文件的文件扩展名添加到PATHEXT环境变量(默认为.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.CPL)中,以在PATHas可执行文件中标识具有这些扩展名的文件。由于Get-Command还表彰这个变量,它可以扩展到列表中的自定义可执行文件。例如

$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缩写形式(set-alias which get-command)快速设置别名。

可在的在线帮助下找到更多信息和示例Get-Command


2
它发现的不仅仅是可执行文件。它还捕获命令文件
Maximilian Burszley

2
@ TheIncorrigible1-如果您的意思是命令文件,例如批处理文件(.BAT.CMD等),则它们被视为可执行文件,因为其扩展名在PATHEXT变量中命名(默认为PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.CPL)。可以通过添加文件扩展名并使用/ 创建可执行文件关联来添加其他可执行文件类型(例如.py.rb等),例如docs.python.org/3.3/using/…–assocftype
shalomb

59

在Windows PowerShell中:

set-alias which where.exe

40

如果已安装PowerShell(建议这样做),则可以使用以下命令作为大致等效项(用programName代替可执行文件的名称):

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

这里还有更多: 我的三明治!PowerShell的哪个


1
我一直在寻找这个确切的powershell命令。我一直在使用where.exe,但是在解析其输出时不得不弄乱错误代码,这远不如本机Powershell解决方案。谢谢!
scobi 2012年

9
但是($Env:Path).Split(";") | Get-ChildItem -filter programName*很容易输入... ;-)
Craig

如果路径中的变量通常由系统解析(也称为%JAVA_HOME%),这也将失败。
dragon788 '17

我无法运行which.exe,但我尝试了此方法并奏效。
Asfand Qazi


24

在Windows CMD which调用中where

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

17

Cygwin是一种解决方案。如果您不介意使用第三方解决方案,那么Cygwin是您的最佳选择。

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


10
Ferruccio前面提到的GnuWin32在这种情况下要好得多,因为您可以将本机放在单独的可执行文件中。
Piotr Dobrogost 2011年

GnuWin32很棒,我可以使用它,但是如果您想要此功能而不安装GnuWin32工具,那么where.exe似乎是正确的选择。虽然,我确实将GnuWin32工具放在网络上的\ bin $共享中,以便可以从未在本地安装它们的工作站(和批处理文件)中使用它们。
克雷格

1
当我们谈论Windows中Cygwin的用法时,我更喜欢:cygpath -w“`which <appname>`”
mpasko256

12

在PowerShell中,它是gcm,它提供有关其他命令的格式化信息。如果只想检索可执行文件的路径,请使用.Source

例如:gcm git(gcm git).Source

花絮:


11

我在PowerShell配置文件中有一个名为“哪个”的函数

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

输出如下所示:

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:

没有其他解决方案对我有用,但是> get-command app.exe | format-list效果很好!
亚历山大·麦克法兰

10

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

Windows平台上的金牌,将所有不错的Unix实用程序都放在标准Windows DOS上。使用了多年。

它包含一个“其中”。请注意,它是区分大小写的。

注意:要安装它,请解压缩zip,然后将... \ UnxUtils \ usr \ local \ wbin \添加到系统路径env变量中。


2
它不区分大小写,我也不得不说哪个java.exe而不是哪个Java-Windows 7
Kalpesh Soni

尽管与换行符有关,但它有一些挫败感。例如,如果您不.输入\ r,则grep将不会匹配EOL 。当然,这是99%的解决方案!
dash-tom-bang

是的,它不区分大小写,但是默认情况下,Windows中的文件名也不区分大小写。
Wernfried Domscheit


8

如果您可以找到免费的Pascal编译器,则可以对其进行编译。至少它可以工作并显示出必要的算法。

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.

21
哇,还有人还在使用Pascal吗?:-)
paxdiablo

6
我想有。但不是我。您是否看到program_date ='1994年3月17日'行?
Mawg说恢复Monica 2010年

1
该单元my_funk;是不必要的。感谢您发布Pascal计划,让我想起了我的青春!可惜Pascal没有发展。
扬尼斯

2
哦,但是确实如此。例如,现在它是面向对象的。lazarus-ide.org上有一个很棒的免费,跨平台,实现和IDE ,Borland的直接后代仍然住在delphi的embarcadero.com/products/delphi,对于入门版,这是非常昂贵的(imo),价格为299美元。以及“可用”版本的1000美元。但是,它是跨平台的-Windows,iOs,Mac,Android。获得试用版或使用Lazarus并感觉自己年轻了20岁,-)
Mawg说

1
@yannis“可惜Pascal没有发展” ...除了'Turbo Pascal'Anders继续设计C#之外,您的意思是?
piers7

7

我在Windows上找到的最好的版本是Joseph Newcomer的“ whereis”实用程序,该实用程序可以从其站点上获得(带有源)。

关于“ whereis”的发展的文章值得一读。


1
最新评论:whereis在Win 7 64位下无法找到64位可执行文件。
Axel Kemper


6

我可以在Internet上找到的Unix的Win32端口都不是令人满意的,因为它们都具有以下一个或多个缺点:

  • 不支持Windows PATHEXT变量。(这定义了在扫描路径之前隐式添加到每个命令的扩展列表,并按顺序排列。)(我使用了很多tcl脚本,没有公开的工具可以找到它们。)
  • 不支持cmd.exe代码页,这使它们无法正确显示带有非ASCII字符的路径。(我对此很敏感,我的名字以ç开头:-))
  • 不支持cmd.exe和PowerShell命令行中的不同搜索规则。(没有任何公开可用的工具在PowerShell窗口中找到.ps1脚本,而在cmd窗口中找不到!)

所以我最终写了我自己的书,正确地支持了以上所有内容。

此处可用:http : //jf.larvoire.free.fr/progs/which.exe


FYI我开源我which.exe工具上面提到的,和其他许多人,在github.com/JFLarvoire/SysToolsLib。您可能在那里获得了最新版本,报告了问题等。
Jean-FrançoisLarvoire's

6

此批处理文件使用CMD变量处理来查找将在路径中执行的命令。注意:当前目录总是在路径之前完成,并且根据使用的API调用,在路径之前/之后搜索其他位置。

@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%)

请参见set /?寻求帮助。


6

我正在使用GOW(在Windows上为GNU),这是Cygwin的简化版。您可以从GitHub抓住它这里

GOW(Windows上的GNU)是Cygwin的轻量级替代方案。它使用便利的Windows安装程序来安装大约130个非常有用的开源UNIX应用程序,这些应用程序被编译为本机win32二进制文件。它设计得尽可能小,大约10 MB,而Cygwin则取决于选项,可以运行超过100 MB。- 关于描述(布伦特·R·马泽尔)

GOW中包含的命令列表的屏幕截图:

在此处输入图片说明



5

只需发布此Windows的一个衬里批处理文件:

C:>type wh.cmd
@for %%f in (%*) do for %%e in (%PATHEXT% .dll .lnk) do for %%b in (%%f%%e) do for %%d in (%PATH%) do if exist %%d\%%b echo %%d\%%b

一个测试:

C:>wh ssh
C:\cygwin64\bin\ssh.EXE
C:\Windows\System32\OpenSSH\\ssh.EXE

如果将代码包装在setlocal enableextensions和中,则不是一排就好了endlocal


2
我希望将其放在多行中,这样我才能理解。;-)
Gringo Suave

4

对于您的Windows XP用户(没有where内置命令),我编写了一个名为rubygem的“ where like”命令whichr

要安装它,请安装Ruby。

然后

gem install whichr

像这样运行:

C:> whichr cmd_here


3
我怀疑您被否决了,因为您建议在Windows XP上执行任何操作。
sebastian-c

1
并没有拒绝投票,但是安装Ruby来实现一个简单的命令也很难。上面有一个for循环,可以将其放入批处理脚本中。
Gringo Suave

2
如果您以详细模式运行,是否会在《巫师》的主题曲中打印开头行?;)
Agi Hammerthief

3

JPSoft的TCC和TCC / LE是CMD.EXE的替代品,它们增加了重要的功能。与OP问题相关的which是TCC系列命令处理器的内置命令。


2

我已经使用了whichnpm 的模块了很长时间,并且效果很好:https//www.npmjs.com/package/which 这是一个很好的多平台替代方案。

现在,我切换到whichGit附带的那个。只需将/usr/bin来自Git 的路径添加到您的路径,通常位于C:\Program Files\Git\usr\bin\which.exe。该which二进制将在C:\Program Files\Git\usr\bin\which.exe。它速度更快,并且按预期运行。


1

尝试这个

set a=%~$dir:1
If "%for%"=="" (Echo %1 not found) else (echo %1 found at %a%)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.