windows - PowerShell 命令的程序路径在哪里?
问题描述
命令“git”可从 PowerShell 获得,我想知道 git 在我的 PC 上安装在哪里,所以我尝试执行这样的“脚本”
PS> where git
但执行后我什么也看不到,只提示输入新命令。问题:如何在 Windows 10 中找到命令的路径?
解决方案
现有的答案很有帮助,但我认为更系统的讨论也有帮助。
tl;博士
where
是 PowerShell的cmdlet的内置别名Where-Object
;要调用外部where.exe
程序,请.exe
显式使用:[1]
# Note the use of '.exe' to disambiguate the external 'where.exe' program
# from PowerShell's built-in 'where' alias (for 'Where-Object').
PS> where.exe git
C:\Program Files\Git\cmd\git.exe
where.exe
,其目的是返回系统路径中的可执行文件的完整路径(在$env:PATH
环境变量中列出的目录之一中),与(遗留命令处理器)无关cmd
:它是Windows 附带的外部可执行文件,并且它可以从任何shell 调用,因此也可以从 PowerShell 调用。
相比之下,cmd
确实有所谓的内部命令,确实只能从 调用cmd
,例如mklink
; 实际上,cmd
您可以使用inwhere <name>
来推断给定的(正在运行的)命令<name>
是否是内部的:如果没有输出,则该命令是内部的(或根本不存在)。
或者,使用与cmdlet等效且更灵活的 PowerShell 对应where.exe
Get-Command
项;它返回System.Management.Automation.CommandInfo
实例(或派生类的实例),其.Source
属性包含表示外部可执行文件的命令信息对象的完整路径:
PS> (Get-Command git).Source
C:\Program Files\Git\cmd\git.exe
笔记:
where.exe
仅查找可执行文件,而Get-Command
默认查找所有命令类型(别名、函数、cmdlet、...) - 请参阅下一节。与, 不同
Get-Command
,where.exe
还查找位于当前目录中的可执行文件。Get-Command
不这样做,因为出于安全原因,PowerShell 在设计上不允许仅按名称调用位于当前目录中的可执行文件- 需要路径(例如,.\foo
)。
PowerShell 有不同类型的命令,它们 - 在名称冲突的情况下 - 具有预定义的优先顺序,以确定哪种类型应该是有效的命令。
也就是说,如果给定的命令名称与两个或更多命令匹配,则它们的类型决定了实际调用哪个命令。
此优先级记录在概念about_Command_Precedence
帮助主题中;简而言之,这是按类型降序排列的命令优先级(最高优先级在前):
- 别名
- 功能
- cmdlet(松散地说:作为编译二进制文件实现的函数)
- 外部可执行文件,包括
*.ps1
脚本文件 - 见底部
查看给定名称存在哪些命令类型-All
Get-Command
的一种简单方法是在调用cmdlet时添加开关,该开关按优先级降序列出匹配的命令;也就是说,首先列出将通过给定名称实际执行的命令。
PS> Get-Command -All where
CommandType Name Version Source
----------- ---- ------- ------
Alias where -> Where-Object
Application where.exe 10.0.18... C:\WINDOWS\system32\where.exe
结果表明,cmdlet 的内置where
别名Where-Object
(其目的是过滤管道输入)是您提交时的有效命令where
,而不是所需的where.exe
可执行文件。
鉴于where.exe
可执行文件名具有.exe
可以将其与别名区分开来的扩展名,使用文件扩展名where
调用是最简单where.exe
的,如顶部所示。
如果这是不可能的(例如,在类 Unix 平台上,可执行文件通常没有文件扩展名,或者如果别名隐藏了函数),您可以使用该-Type
参数来获取感兴趣的命令,并调用它&
,呼叫运营商:
# Invokes where.exe, as only it is of type 'Application' (external executable)
& (Get-Command -Type Application where) git
如果有多个基本文件名为 的外部可执行文件,它将执行最早where
列出的目录中的那个 - 请参阅下一节。$env:PATH
外部可执行文件和*.ps1
脚本之间的优先级:
笔记:
与 PowerShell之间的一个重要区别
cmd
是 PowerShell - 出于安全原因的设计 -不允许您仅按名称.ps1
调用位于当前目录中的外部可执行文件或脚本;为此,您必须使用path,在最简单的情况下通过前置(or ); 例如,要调用位于当前目录中的可执行文件,您必须使用.\
./
foo
./foo ...
实际上,脚本和其他可执行文件之间的优先级
*.ps1
因平台(Windows 与类 Unix 平台)而异,如下所述。下面的讨论假定给定的命令名称不会被优先级更高的命令类型(例如别名)所掩盖,并解析为外部可执行文件或
*.ps1
脚本。
优先规则:
当命令名称通过环境变量中列出的目录解析为潜在的多个外部可执行文件或脚本时,将调用位于最早列出的目录中的可执行文件/脚本。
*.ps1
$env:PATH
如果,在那个最早的目录中:
给定的名称与可执行文件名(例如
where.exe
)或脚本(例如foo.ps1
)完全匹配,没有歧义,并且调用了该可执行文件/脚本。给定的名称不包括文件扩展名(例如,
foo
),多个可执行文件可以匹配(通过隐含的文件扩展名),并且实际调用的文件确定如下:在Windows上:
PowerShell 优先考虑自己的脚本,因此如果存在
.ps1
脚本,则它是有效的命令;请注意,.ps1
脚本是在进程内执行的,与外部可执行文件不同,后者总是在子进程中运行。否则,它是环境变量中的可执行扩展名中文件扩展名最早列出
$env:PATHEXT
的可执行文件;例如,foo.bat
优先于foo.vbs
,因为.BAT
列在 之前.VBS
。
在类 Unix 平台(Linux、macOS)上:
类 Unix 平台仅通过权限来确定可执行性,而不是通过文件扩展名,并且在绝大多数情况下,可执行文件没有文件扩展名(例如,只是
git
,不像git.exe
在 Windows 上那样)。从 PowerShell 的角度来看,与 Unix 上的可执行性相关的唯一文件扩展名是
.ps1
,因为PowerShell 本身认为这些文件是可执行的——无论它们是否从系统的角度来看。因此,在 Unix 上的 PowerShell 中,
.ps1
是唯一可以在调用时省略的隐含文件扩展名;例如,您可以直接调用脚本文件foo.ps1
(foo
假设它在系统路径中)。如果您有一个外部可执行文件,其文件名没有文件扩展名 - 通常情况下 - 以及
.ps1
同一目录中具有相同基本名称的文件,则外部可执行文件优先 - 原因是扩展名 - less name与无扩展名的可执行文件名完全匹配。- 例如,如果外部可执行文件位于相同(最早的)目录中,则提交会调用外部可执行文件,这与 Windows 不同。
foo
foo.ps1
foo
foo.ps1
- 例如,如果外部可执行文件位于相同(最早的)目录中,则提交会调用外部可执行文件,这与 Windows 不同。
笔记:
当使用显式路径(没有文件扩展名)时,给定目录中多个可执行文件之间的优先规则也适用;例如,调用
./foo
决定了当前目录中多个可执行文件之间的优先级,其基本名称foo
如上所述。将
.ps1
脚本放置在列出的目录中$env:PATH
并仅通过(基本)名称调用它们并不是很常见,尽管值得考虑将其作为在文件中放置潜在许多函数$PROFILE
的替代方法。- 不幸的是,Linux上的 UX 很差,由于它区分大小写的文件系统,您必须在调用时指定(基本)文件名完全大小写,而 PowerShell 命令调用不区分大小写;例如,如果实际文件名是
Get-Foo.ps1
,则仅Get-Foo
适用于调用,而不适用于get-foo
.
- 不幸的是,Linux上的 UX 很差,由于它区分大小写的文件系统,您必须在调用时指定(基本)文件名完全大小写,而 PowerShell 命令调用不区分大小写;例如,如果实际文件名是
[1] 至于为什么诸如where git
- 即错误使用Where-Object
- 之类的调用不会产生输出:该调用Where-Object git
相当于输出。Where-Object { $_.git }
推荐阅读
- javascript - 如何在 1 个不和谐服务器中切换命令,而不是在机器人所在的所有不和谐服务器之间切换?
- c# - 在 C# 中做一个直方图向后投影
- linux - 使用 sed 删除 bash 脚本中包含精确字符串的行
- css - 我将如何在 Web Animation API 中重新创建以下 CSS 代码
- c# - 想通过c#发送outlook会议邀请
- python - 优化 os.walk() 迭代;在 64 位、4 核、64 GB、2.50GHz 系统上
- mysql - MySQL BEFORE INSERT TRIGGER 不影响第一个记录条目
- pattern-matching - Idris 中产品的模式匹配
- javascript - Bootbox 警报抛出“未捕获的 TypeError:div.on 不是函数”
- java - 在同一个应用程序中使用两个 Google API