在 powershell 中制作 Alias 的最简单方法是什么?
What is the simplest way to make Alias in powershell?
我想知道是否有任何简单的方法可以像 cmd 一样为 powershell 创建别名。
例如:在 cmd 中,doskey art=php artisan $*
其中 $*
是可选的。目前,我在 powershell 中使用以下别名。
function runArtisanCommand
{
param(
[Parameter(Mandatory=$false, Position = 0, ValueFromRemainingArguments = $true)]
$command
)
php artisan $command
}
Set-Alias art runArtisanCommand
这有点管用,但不带标志。例如:我不会写 art -h
或 art route:list -c
。在 art -h
命令中,它打印 php artisan
的输出并且根本不读取标志,但在 art route:list -c
命令中,它出错了。
runArtisanCommand : Missing an argument for parameter 'command'. Specify a parameter of type 'System.Object' and try again.
At line:1 char:16
+ art route:list -c
+ ~~
+ CategoryInfo : InvalidArgument: (:) [runArtisanCommand], ParameterBindingException
+ FullyQualifiedErrorId : MissingArgument,runArtisanCommand
我希望有比这更简单的解决方案。提前致谢。
传递未知参数的最简单和最方便的方法是 spatting
automatic $args
array - 作为 @args
- 在 简单 函数或脚本 中(既不使用 [CmdletBinding()]
也不使用 [Parameter()]
属性):
# Note: @args rather than $args makes the function work with named
# arguments for PowerShell commands too - see explanation below.
function runArtisanCommand { php artisan @args }
# As in your question: Define alias 'art' for the function
# Note: Of course, you could directly name your *function* 'art'.
# If you do want the function to have a longer name, consider one
# that adheres to PowerShell's Verb-Noun naming convention, such as
# 'Invoke-ArtisanCommand'.
Set-Alias art runArtisanCommand
顺便说一句:由于目标可执行文件 php
既未 引用 也未根据 变量指定或expression,可以原样调用;否则,您将需要 &
,call operator - see 以获得背景信息。
至于你试过的:
问题是使用 -c
作为 直通 参数仅当您在其前面加上 --
:
时才有效
# OK, thanks to '--'
art -- route:list -c
--
告诉 PowerShell 将所有剩余参数视为 未命名(位置)参数,而不是尝试将 -c
等标记解释为 参数名称.
如果没有 --
,-c
将被解释为引用您的 -command
参数 (您声明为 $command
的参数ValueFromRemainingArguments = $true
),假设 PowerShell 允许您指定名称 prefixes 来代替完整的参数名称,只要给定的前缀是明确的。
因为 [switch]
以外的任何类型的参数都需要关联的参数,-c
(又名 -command
)失败并显示一条错误消息。
您可以通过命名参数来避免冲突,这样它就不会与任何传递参数发生冲突,例如将其命名为-_args
(带参数变量 $_args
):
function runArtisanCommand
{
param(
# Note: `Mandatory = $false` and `Position = 0` are *implied*.
[Parameter(ValueFromRemainingArguments)]
$_args
)
php artisan @_args
}
但是,鉴于 使用 [Parameter()]
属性隐含地使您的函数成为 advanced function, it invariably also accepts common parameters,例如 -ErrorAction
、-OutVariable
、-Verbose
... - 所有这些都可以通过明确的前缀/短别名传递;例如,-outv
代表 -OutVariable
,或别名 -ea
代表 ErrorAction
; 与他们的碰撞是不可避免的.
因此,-e
still 等预期的传递参数将不起作用:
# FAILS, because -e ambiguously matches common parameters -ErrorAction
# and -ErrorVariable.
PS> art router:list -e
Parameter cannot be processed because the parameter name 'e' is ambiguous.
Possible matches include: -ErrorAction -ErrorVariable.
同样,需要--
:
# OK, thanks to '--'
art -- router:list -e
总结:
特别是函数包装对外部程序的调用,例如php.exe
,使用simple function with @args
,如顶部所示,不仅更简单,而且更健壮。
对于 函数包装 PowerShell 命令(带有显式声明的参数):
- 一个 简单的 函数与
@args
一起工作,
- 但如果您还希望支持制表符完成和显示syntax diagram with the supported parameters, by passing
-?
, or via Get-Help
,请考虑定义一个(总是高级) 代理(包装)函数 通过 PowerShell SDK - 见下文。
可选背景信息:PowerShell 中的传递参数
作为 Mathias R. Jessen points out, the simplest way to pass (undeclared) arguments passed to a function or script through to another command is to use the automatic $args
variable, which is an automatically populated array of all the arguments passed to a simple function or script (one that isn't advanced,通过使用 [CmdletBinding()]
and/or [Parameter()]
属性)。
至于为什么要用@args
而不是$args
:
在包装函数中按原样使用 $args
仅适用于传递 positional 参数(那些没有以参数名称为前缀的参数;例如, *.txt
), 而不是 named 参数 (例如, -Path *.txt
).
如果最终目标命令是外部程序(例如本例中的php.exe
),这不是问题,因为PowerShell 然后将 所有 参数视为位置参数(它无法知道目标程序的语法)。
但是,如果最终调用 PowerShell 命令(带有正式声明的参数),则只有 splatting $args
数组 -这在语法上意味着我们 @args
相反 - 支持通过 named 参数传递。[1]
因此,作为一种习惯,我建议总是在简单的包装函数中使用 @args
,它同样适用于外部程序。[ 2]
举一个简单的包装函数的例子 Get-ChildItem
:
# Simple wrapper function for Get-ChildItem that lists recursively
# and by relative path only.
function dirTree {
# Use @args to make sure that named arguments are properly passed through.
Get-ChildItem -Recurse -Name @args
}
# Invoke it with a *named* argument passed through to Get-ChildItem
# If $args rather than @args were used inside the function, this call would fail.
dirTree -Filter *.txt
使用代理函数进行更复杂的直通处理:
使用@args
很方便,但代价是不支持以下:
tab-completion,假设 tab-completion 仅适用于正式声明的参数(通常使用 param(...)
块)。
显示 syntax diagram with the supported parameters, by passing -?
, or via Get-Help
要克服这些限制,最终目标命令的参数声明必须重复 在(然后是高级的)包装函数中;虽然这很麻烦,但 PowerShell 可以通过 PowerShell SDK 构建所谓的 代理(包装器)函数 来自动执行该过程 - 请参阅 .
注:
关于常见的参数如-ErrorAction
,是代理函数本身(自动)处理它们,但不应该'对来电者没有影响。
脚手架代理函数仅适用于 PowerShell 命令,因为 PowerShell 不了解外部程序的语法。
- 但是,您可以手动复制外部目标程序的参数声明。
[1] 请注意,自动 $args
数组具有支持此功能的内置魔法;使用 splatting 传递命名参数 not 支持自定义 array 并且需要使用 hash table 代替,如帮助中所述关于上面链接的 splatting 的主题。
[2]其实只有@args
也支持--%
的正确解释,stop-parsing symbol.
我想知道是否有任何简单的方法可以像 cmd 一样为 powershell 创建别名。
例如:在 cmd 中,doskey art=php artisan $*
其中 $*
是可选的。目前,我在 powershell 中使用以下别名。
function runArtisanCommand
{
param(
[Parameter(Mandatory=$false, Position = 0, ValueFromRemainingArguments = $true)]
$command
)
php artisan $command
}
Set-Alias art runArtisanCommand
这有点管用,但不带标志。例如:我不会写 art -h
或 art route:list -c
。在 art -h
命令中,它打印 php artisan
的输出并且根本不读取标志,但在 art route:list -c
命令中,它出错了。
runArtisanCommand : Missing an argument for parameter 'command'. Specify a parameter of type 'System.Object' and try again.
At line:1 char:16
+ art route:list -c
+ ~~
+ CategoryInfo : InvalidArgument: (:) [runArtisanCommand], ParameterBindingException
+ FullyQualifiedErrorId : MissingArgument,runArtisanCommand
我希望有比这更简单的解决方案。提前致谢。
传递未知参数的最简单和最方便的方法是 spatting
automatic $args
array - 作为 @args
- 在 简单 函数或脚本 中(既不使用 [CmdletBinding()]
也不使用 [Parameter()]
属性):
# Note: @args rather than $args makes the function work with named
# arguments for PowerShell commands too - see explanation below.
function runArtisanCommand { php artisan @args }
# As in your question: Define alias 'art' for the function
# Note: Of course, you could directly name your *function* 'art'.
# If you do want the function to have a longer name, consider one
# that adheres to PowerShell's Verb-Noun naming convention, such as
# 'Invoke-ArtisanCommand'.
Set-Alias art runArtisanCommand
顺便说一句:由于目标可执行文件 php
既未 引用 也未根据 变量指定或expression,可以原样调用;否则,您将需要 &
,call operator - see
至于你试过的:
问题是使用 -c
作为 直通 参数仅当您在其前面加上 --
:
# OK, thanks to '--'
art -- route:list -c
--
告诉 PowerShell 将所有剩余参数视为 未命名(位置)参数,而不是尝试将 -c
等标记解释为 参数名称.
如果没有 --
,-c
将被解释为引用您的 -command
参数 (您声明为 $command
的参数ValueFromRemainingArguments = $true
),假设 PowerShell 允许您指定名称 prefixes 来代替完整的参数名称,只要给定的前缀是明确的。
因为 [switch]
以外的任何类型的参数都需要关联的参数,-c
(又名 -command
)失败并显示一条错误消息。
您可以通过命名参数来避免冲突,这样它就不会与任何传递参数发生冲突,例如将其命名为-_args
(带参数变量 $_args
):
function runArtisanCommand
{
param(
# Note: `Mandatory = $false` and `Position = 0` are *implied*.
[Parameter(ValueFromRemainingArguments)]
$_args
)
php artisan @_args
}
但是,鉴于 使用 [Parameter()]
属性隐含地使您的函数成为 advanced function, it invariably also accepts common parameters,例如 -ErrorAction
、-OutVariable
、-Verbose
... - 所有这些都可以通过明确的前缀/短别名传递;例如,-outv
代表 -OutVariable
,或别名 -ea
代表 ErrorAction
; 与他们的碰撞是不可避免的.
因此,-e
still 等预期的传递参数将不起作用:
# FAILS, because -e ambiguously matches common parameters -ErrorAction
# and -ErrorVariable.
PS> art router:list -e
Parameter cannot be processed because the parameter name 'e' is ambiguous.
Possible matches include: -ErrorAction -ErrorVariable.
同样,需要--
:
# OK, thanks to '--'
art -- router:list -e
总结:
特别是函数包装对外部程序的调用,例如
php.exe
,使用simple function with@args
,如顶部所示,不仅更简单,而且更健壮。对于 函数包装 PowerShell 命令(带有显式声明的参数):
- 一个 简单的 函数与
@args
一起工作, - 但如果您还希望支持制表符完成和显示syntax diagram with the supported parameters, by passing
-?
, or viaGet-Help
,请考虑定义一个(总是高级) 代理(包装)函数 通过 PowerShell SDK - 见下文。
- 一个 简单的 函数与
可选背景信息:PowerShell 中的传递参数
作为 Mathias R. Jessen points out, the simplest way to pass (undeclared) arguments passed to a function or script through to another command is to use the automatic $args
variable, which is an automatically populated array of all the arguments passed to a simple function or script (one that isn't advanced,通过使用 [CmdletBinding()]
and/or [Parameter()]
属性)。
至于为什么要用@args
而不是$args
:
在包装函数中按原样使用
$args
仅适用于传递 positional 参数(那些没有以参数名称为前缀的参数;例如,*.txt
), 而不是 named 参数 (例如,-Path *.txt
).如果最终目标命令是外部程序(例如本例中的
php.exe
),这不是问题,因为PowerShell 然后将 所有 参数视为位置参数(它无法知道目标程序的语法)。但是,如果最终调用 PowerShell 命令(带有正式声明的参数),则只有 splatting
$args
数组 -这在语法上意味着我们@args
相反 - 支持通过 named 参数传递。[1]
因此,作为一种习惯,我建议总是在简单的包装函数中使用 @args
,它同样适用于外部程序。[ 2]
举一个简单的包装函数的例子 Get-ChildItem
:
# Simple wrapper function for Get-ChildItem that lists recursively
# and by relative path only.
function dirTree {
# Use @args to make sure that named arguments are properly passed through.
Get-ChildItem -Recurse -Name @args
}
# Invoke it with a *named* argument passed through to Get-ChildItem
# If $args rather than @args were used inside the function, this call would fail.
dirTree -Filter *.txt
使用代理函数进行更复杂的直通处理:
使用@args
很方便,但代价是不支持以下:
tab-completion,假设 tab-completion 仅适用于正式声明的参数(通常使用
param(...)
块)。显示 syntax diagram with the supported parameters, by passing
-?
, or viaGet-Help
要克服这些限制,最终目标命令的参数声明必须重复 在(然后是高级的)包装函数中;虽然这很麻烦,但 PowerShell 可以通过 PowerShell SDK 构建所谓的 代理(包装器)函数 来自动执行该过程 - 请参阅
注:
关于常见的参数如
-ErrorAction
,是代理函数本身(自动)处理它们,但不应该'对来电者没有影响。脚手架代理函数仅适用于 PowerShell 命令,因为 PowerShell 不了解外部程序的语法。
- 但是,您可以手动复制外部目标程序的参数声明。
[1] 请注意,自动 $args
数组具有支持此功能的内置魔法;使用 splatting 传递命名参数 not 支持自定义 array 并且需要使用 hash table 代替,如帮助中所述关于上面链接的 splatting 的主题。
[2]其实只有@args
也支持--%
的正确解释,stop-parsing symbol.