如果 'where' 返回多个结果,哪个可执行文件是 DOS/CMD 运行?

Which executable is run by DOS/CMD if multiple results are returned by 'where'?

我正在 运行ning Win10,安装了 Cygwin,Git Windows 和 Ubuntu WSL 安装。
运行 这些命令在 DOS 和 Powershell 中 returns 结果如下:

# DOS
C:\>where grep
C:\cygwin64\bin\grep.exe
C:\Program Files\Git\usr\bin\grep.exe

# DOS
C:\>which grep
/usr/bin/grep

# Powershell
C:\> gcm grep*

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Application     grep.exe                                           0.0.0.0    C:\cygwin64\bin\grep.exe
Application     grep.exe                                           0.0.0.0    C:\Program Files\Git\usr\bin\grep.exe

现在当我运行这个的时候,以上哪一个实际上是运行?

# DOS / Powershell
C:\>grep ... ---> ?

它是运行按照它们出现在这里的顺序,还是在 PATH 环境变量中列出?或者另一个订单(哪个)?

术语 撇开:我假设你的意思是 cmd.exe aka the Command Prompt, the command shell of modern Windows versions, not the long-obsolete (MS-)DOS 及其 command.com对口。

Is it run in the order they appear here, or are listed in PATH environment variable? Or another order (which one)?

是的,第一个 可执行文件的路径在您的调用结果中列出,如果您提交 grep 将调用该可执行文件,即仅文件 name,作为命令。

但是,请注意,您应该调用 gcm grep,而不是 gcm grep*,这样您只会收到 一个 结果,因为 Get-Command (whose built-in alias is gcm), when given a literal name (rather than a wildcard 表达式),只有 returns 默认情况下该命令的 有效 形式/路径,就像 Unix which 实用程序一样。

Get-Commandwhich都需要opt-in如果你想知道所有形式/ 给定名称的路径,即分别通过 -All-a,在这种情况下,它们按优先级降序排列,即 effective 一个先打印。

where.exe,相比之下,总是打印所有路径,按优先级降序排列。

外部程序中——这是whichwhere.exe考虑的唯一命令形式——决定优先级的是 PATH 环境变量中列出目录的顺序:在列出的目录中按顺序查找具有给定名称的可执行文件,第一个发现是有效的。

在Windows上,如果没有给出file-name扩展名,则依次应用PATHEXT环境变量中列出的扩展名来寻找完整的文件名,例如,grep 找到 grep.exe

Get-Command 默认情况下还会查找 PowerShell-specific 命令形式,以别名、函数、cmdlet 以及 .ps1 脚本文件,在考虑外部程序之前按此顺序。 您可以使用 -Type Application 限制对外部程序的查找,但请注意 在调用时 您可能必须 包含文件扩展名 以便绕过另一个优先的命令形式。
例如,where 会查找/调用 Where-Object cmdlet(其中一个 built-in 别名是 where),而 where.exe 会找到/调用 外部程序 。 在 Unix-like 平台上,外部程序通常没有扩展,调用时需要做更多的工作;例如,要调用假设的 where 程序而不意外调用 Where-Object cmdlet,您必须使用
& (Get-Command -Type Application where)

请注意,原则上这同样适用于 cmd.exe 和 POSIX-compatible shell:它们也有 internal 命令可以隐藏同名的外部程序(例如,cmd.exe 中的 dir 和 Bash 中的 printf);在 cmd.exe 中,您可以再次使用可执行文件的 file-name 扩展名来确保外部程序是有针对性的;例如,在 POSIX-compatible shell 中,您可以通过 $(which printf) 调用。

简而言之:PowerShell 中只有 Get-Command 为您提供了 完整的 图片,说明给定名称将实际调用的命令; where.exewhich 实用程序 - 必然 - 仅限于 外部程序 .

最后,正如 Mofi 指出的,cmd.exe 与 PowerShell 和 POSIX-compatible shell 之间存在重要区别:

  • cmd.exe 允许您仅按名称执行位于 当前 目录中的外部程序。

  • 根据 security-minded 设计,PowerShell 和 POSIX-compatible shell 支持,并且需要 路径 引用本例中的程序;最简单的形式:.\foo.exe / ./foo.

  • where.exe does 报告 current 目录中的可执行文件,因此如果您从 PowerShell 调用它,你可能会得到误报;也就是说,考虑到更灵活的 Get-Command cmdlet 的可用性,没有充分的理由从 PowerShell 调用 where.exe