2638

由于我有时会遇到路径问题,我自己的一个 cmd 脚本被另一个程序(路径的早期)隐藏(阴影),我希望能够在 Windows 命令行上找到程序的完整路径,给定只是它的名字。

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

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

4

26 回答 26

2824

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

尝试where /?寻求帮助。

请注意,Windows PowerShell 定义wherecmdletWhere-Object别名,因此如果需要where.exe,您需要键入全名而不是省略.exe扩展名。或者,您可以为其设置别名:

Set-Alias which where.exe

更新:建议使用Get-Command(alias: gcm),因为它是 PS 原生的,并且将获取所有命令类型:别名、cmdlet、可执行文件和函数。例子:

gcm notepad*
于 2008-11-20T05:52:50.717 回答
307

虽然更高版本的 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

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

于 2008-11-20T05:48:16.437 回答
208

在 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让你定义别名,which可以这样定义。

$ sal which gcm   # short form of `Set-Alias which Get-Command`
$ which foo
...

PowerShell命令不仅仅是可执行文件(.exe、、.ps1等)。它们也可以是 cmdlet、函数、别名、在 中设置的自定义可执行后缀$Env:PATHEXTGet-Command,能够找到并列出所有这些命令(非常类似于 Bash 的type -a foo)。仅此一项就使其优于where.exe,which.exe等,后者通常仅限于查找可执行文件。

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

$ 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
...

查找自定义可执行文件

与 UNIX 不同,其中可执行文件是+x设置了可执行 ( ) 位的文件,Windows 上的可执行文件是存在于$PATHenv 中指定的目录之一中的文件。$PATHEXT文件名后缀在env中命名的变量。变量(默认为.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.CPL)。

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

有关Get-Command更多选项和示例,请参阅。

于 2014-11-26T02:07:07.443 回答
68

在 Windows PowerShell 中:

set-alias which where.exe
于 2012-11-30T23:00:43.940 回答
44

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

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

更多在这里: 我的曼维奇!PowerShell 哪个

于 2008-11-20T05:16:34.300 回答
37

GnuWin32工具有,which以及一大堆其他 Unix 工具。

于 2008-11-20T06:44:18.583 回答
30

在 Windows CMDwhich调用中where

$ where php
C:\Program Files\PHP\php.exe
于 2016-04-01T12:02:00.997 回答
18

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

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

于 2010-10-12T17:02:50.700 回答
13

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

例如:gcm git(gcm git).Source

花絮:

于 2015-09-11T11:32:27.977 回答
12

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

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:
于 2015-07-31T08:59:57.177 回答
11

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

windows平台上的gold,将所有漂亮的unix实用程序放在标准的windows DOS上。多年来一直在使用它。

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

注意:要安装它,请在某处爆炸 zip 并将 ...\UnxUtils\usr\local\wbin\ 添加到您的系统路径 env 变量中。

于 2010-03-26T00:08:43.000 回答
10

如果你能找到一个免费的 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.
于 2010-03-26T00:50:50.313 回答
8

Windows 没有库存,但它由Services for Unix提供,并且有几个简单的批处理脚本漂浮在周围,可以完成同样的事情,比如这个

于 2008-11-20T04:28:14.117 回答
7

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

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

于 2008-11-20T05:09:19.853 回答
6

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

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

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

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

于 2014-12-18T13:29:59.033 回答
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 /?寻求帮助。

于 2016-09-25T01:45:38.527 回答
6

您可以先从Downloading Git安装 Git ,然后打开 Git Bash 并输入:

which app-name
于 2017-08-02T06:40:45.337 回答
6

我正在使用 GOW(Windows 上的 GNU),它是 Cygwin 的轻量级版本。可以从 GitHub 获取它。

GOW(Windows 上的 GNU)是 Cygwin 的轻量级替代品。它使用一个方便的 Windows 安装程序来安装大约 130 个非常有用的开源 UNIX 应用程序,这些应用程序编译为本地 win32 二进制文件。它被设计为尽可能小,大约 10 MB,而 Cygwin 可以运行超过 100 MB,具体取决于选项。-关于描述(Brent R. Matzelle)

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

在此处输入图像描述

于 2017-12-13T08:58:21.117 回答
5

我创建了类似于 Ned Batchelder 的工具:

在 PATH 中搜索 .dll 和 .exe 文件

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

于 2008-11-20T09:39:21.383 回答
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

于 2019-10-08T11:37:56.077 回答
4

对于 Windows XP 用户(没有where内置命令),我编写了一个“where like”命令作为 ruby​​gem,名为whichr.

要安装它,请安装 Ruby。

然后

gem install whichr

像这样运行它:

C:> whichr cmd_here

于 2015-09-02T14:59:42.553 回答
3

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

于 2017-02-09T23:31:11.057 回答
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. 它速度更快,也可以按预期工作。

于 2018-06-01T02:02:25.593 回答
1

试试这个

set a=%~$dir:1
If "%for%"=="" (Echo %1 not found) else (echo %1 found at %a%)
于 2019-05-03T13:00:18.793 回答
0

可以下载为 Windows 编译的所有 UNIX 命令,包括which从这个 GitHub 存储库:https ://github.com/George-Ogden/UNIX

于 2020-07-04T17:44:52.023 回答
-1

这是我用来查找可执行文件的函数,类似于 Unix 命令“WHICH”

app_path_func.cmd:

@ECHO OFF
CLS

FOR /F "skip=2 tokens=1,2* USEBACKQ" %%N IN (`reg query "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\%~1" /t REG_SZ  /v "Path"`) DO (
 IF /I "%%N" == "Path" (
  SET wherepath=%%P%~1
  GoTo Found
 )
)

FOR /F "tokens=* USEBACKQ" %%F IN (`where.exe %~1`) DO (
 SET wherepath=%%F
 GoTo Found
)

FOR /F "tokens=* USEBACKQ" %%F IN (`where.exe /R "%PROGRAMFILES%" %~1`) DO (
 SET wherepath=%%F
 GoTo Found
)

FOR /F "tokens=* USEBACKQ" %%F IN (`where.exe /R "%PROGRAMFILES(x86)%" %~1`) DO (
 SET wherepath=%%F
 GoTo Found
)

FOR /F "tokens=* USEBACKQ" %%F IN (`where.exe /R "%WINDIR%" %~1`) DO (
 SET wherepath=%%F
 GoTo Found
)

:Found
SET %2=%wherepath%
:End

测试:

@ECHO OFF
CLS

CALL "app_path_func.cmd" WINWORD.EXE PROGPATH
ECHO %PROGPATH%

PAUSE

结果:

C:\Program Files (x86)\Microsoft Office\Office15\
Press any key to continue . . .

https://www.freesoftwareservers.com/display/FREES/Find+Executable+via+Batch+-+Microsoft+Office+Example+-+WINWORD+-+Find+Microsoft+Office+Path

于 2020-08-05T03:27:18.173 回答