Windows PowerShell 2.0 开发之命令别名


UNIX shell的用户已经能够为命令添加更简短和友好的别名,但遗憾的是DOS基于的shell,command.com和cmd.exe缺少这个特性。而其他第三方工具,如doskey.exe允许用户为命令定义别名,但不是基于shell的,而且用户需要记忆难记的语法。PowerShell最终填补了Windows shell的这个空白,而且提供了内置的对命令别名的支持。

PowerShell提供的大部分命令在初始化安装时创建,Version 2.0 CTP3提供了百余个内置的cmdlet。下例检索在系统中注册的cmdlet的数目:

PS C:\>(Get-Command –type Cmdlet).Length
235

在这些内置的cmdlet中PowerShell提供了大量的编程规则和建议,所有的名称和参数都是以便于用户学习和使用的方式命名的。

除了部分别名是专为实现与其他界面的名称兼容性而设计的以外,其他PowerShell中的内置别名通常是为了简短易用而设计的。这些简短的名称便于快速键入,但是如果不了解其含义,则无法解读。

通过提供一组基于常用动词和名词的速记名称的标准别名,PowerShell试图在清晰性与简短性之间取得平衡。这样在一组常用cmdlet 的核心别名中,只需了解速记名称即可解读这些命令。例如,在标准别名中动词Get缩写为g,动词Set缩写为s,名词Item缩写为i,名词Location 缩写为l,而名词Command缩写为cm。以下简短示例说明了这一工作机制,Get-Item 的标准别名通过将表示Get的g与表示Item的i组合而获得,即gi;Set-Item的标准别名通过将表示Set的s与表示Item的i组合而获得,即si;Get-Location的标准别名通过将表示Get的g与表示Location的l组合而获得,即gl;Set-Location的标准别名通过将表示Set的s与表示Location的l组合而获得,即sl;Get-Command的标准别名是通过将表示Get的g与表示Command的cm组合而获得,即gcm。

创建别名

别名用来关联某个名字和某命令,如果要用指向Write-Host的log别名来实现输出,需要调用New-Alias这个cmdlet来实现:

PS C:\>New-Alias log  Write-Host
PS C:\>

接下来即可在代码中使用这个别名:

PS C:\> log “Ouput With log alias Operation Completed Successfully”
PS C:\> Ouput With log alias Operation Completed Successfully

如果别名已经存在,New-Alias会抛出错误;

PS C:\> New-Alias log Get-ChildItem
New-Alias : Alias not allowed because an alias with the name ‘log’ already exists.
At line:1 char:10
+ New-Alias  <<<< log Get-ChildItem

可以通过检查别名清单来确认要使用的别名是否可用,使用的方法为Get-Alias、Get-Command或Alias提供者。

(1)Get-Alias

这个cmdlet返回系统中所有的别名或根据传递给过滤器的参数只返回相应的别名,下例返回所有以l开头的别名:

PS C:\> Get-Alias l*

CommandType     Name     Definition
-----------------     ------      ---------
Alias                lp         Out-Printer
Alias                ls         Get-ChildItem
Alias                lp         Out-Printer

可以使用if语句判断特定别名是否存在:

PS C:\> if(Get-Alias log)
>> {
>>log “Alias exists”
>> }
Alias exists

上例假设之前定义的别名存在,则输出信息;如果未输出,则说明别名不存在或者log这个别名指向的命令并不是Write-Host,这里使用这个技巧是因为之前定义的别名log指向Write-Host。

(2)Get-Command

别名相当于命令的快捷方式,使用Get-Command也可找出,为此需要将CommandType参数设置为Alias。如果需要缩小查找范围,则可以增加过滤器。下例获取以l开头的别名:

PS C:\PowerShell> Get-Command -CommandType Alias l*

CommandType     Name                            Definition
-----------     ----                            ----------
Alias           log                             Write-Host
Alias           lp                              Out-Printer
Alias           ls                              Get-ChildItem

需要强调的是上例与通过Get-Alias得到的输出结果一致,两个cmdlet在获取别名方面的效果相同,返回的都是别名对应的对象类型AliasInfo。

(3)别名提供程序

默认情况下别名提供程序映射到类似文件系统的alias:驱动器,下例通过其获取所有以l开头的别名:

PS C:\PowerShell> cd alias:
PS Alias:\> dir l*
CommandType     Name                            Definition
-----------     ----                            ----------
Alias           lp                              Out-Printer
Alias           ls                              Get-ChildItem
Alias           log                             Write-Host

同样,在这里获取到的还是AliasInfo对象的集合,因为别名提供程序返回的是这个类型的对象。Test-Path cmdlet可以判断某个文件或目录是否存在,这样即可使用Test-Path重写前面的if语句来判断特定别名是否存在,如下例:

PS C:\PowerShell> if(Test-Path alias:\log)
>> {
>>     log "Alias exists"
>> }
>>
Alias exists

修改别名

很多时候用户需要修改别名,或显式地用自己的别名覆盖已经存在的别名。如果别名已经存在,再次使用New-Alias cmdlet创建相同的别名将会抛错,如果需要强制覆盖已存在的别名,则可以传递Force的开关参数。此时New-Alias将会把抛出的错误在后台销毁,并删除已有的旧别名,然后创建新的别名。下例更新log这个别名,使用Write-Verbose替换Write-Host:

PS C:\PowerShell> Get-Alias log

CommandType     Name                      Definition
-----------          ----                        ----------
Alias               log                         Write-Host

PS C:\PowerShell> New-Alias log Write-Verbose -Force
PS C:\PowerShell> Get-Alias log

CommandType     Name                      Definition
-----------          ----                        ----------
Alias               log                         Write-Verbose

PS C:\PowerShell> $VerbosePreference ="Continue"
PS C:\PowerShell> log "This is just a test"
VERBOSE: This is just a test

需要强调的是,由于在上例中使用了Write-Verbose这个用于调试的cmdlet,可以需要设置$VerbosePreference全局变量为Continue,这样会将错误报告给用户并继续执行后面的代码。用户可以从第11章学到更多关于脚本调试的技术,包括跟踪、步进调试脚本代码。

为了避免由于强制更新别名,覆盖已有的重要别名,PowerShell提供了另外一个可选的修改别名的cmdlet,即Set-Alias。其工作方式类似New-Alias –Force,但是更简练。下例将log别名的指向改回Write-Host:

PS C:\PowerShell> Set-Alias log Write-Host
PS C:\PowerShell> Get-Alias log

CommandType     Name                          Definition
-----------          ----                            ----------
Alias               log                             Write-Host

PS C:\PowerShell> log "Write-Host is back"
Write-Host is back

由于别名在别名提供程序Alias:中是以一条类似文件的记录的形式存在,因此可以通过使用Set-Item cmdlet设置相应的记录。操作的方式如下例所示:

PS C:\PowerShell> cd Alias:
PS Alias:\> Set-Item log Write-Verbose
PS Alias:\> dir log

CommandType     Name                          Definition
-----------          ----                            ----------
Alias               log                             Write-Verbose

别名既然可以作为类似文件记录的形式操作,因此可以通过调用Set-Content cmdlet修改别名。下例通过设置别名记录的内容来使别名重新指向:

PS C:\PowerShell> cd alias:
PS Alias:\> Set-Content log Write-Host
PS Alias:\> dir log

CommandType     Name                          Definition
-----------          ----                            ----------
Alias               log                             Write-Host

PowerShell中并没有提供专门的cmdlet来删除或清理无用的别名,为了维护别名,需要使用别名提供程序,并调用Remove-Item cmdlet(别名是“del”)移除无用的别名。下例演示移除log别名的方法:

PS C:\PowerShell> cd alias:
PS Alias:\> del log
PS Alias:\> Get-Alias log
Get-Alias : This command cannot find a matching alias because alias with name '
log' do not exist.
At line:1 char:10
+ Get-Alias <<<<  log
    + CategoryInfo          : ObjectNotFound: (log:String) [Get-Alias], ItemNo
   tFoundException
    + FullyQualifiedErrorId : ItemNotFoundException,Microsoft.PowerShell.Comma
   nds.GetAliasCommand

从上例能够看到,log别名已经被清除,通过Get-Alias获取该别名时抛错。

导入/导出别名

可以导出已经定义的别名,也可以在目标计算机上导入这些别名。

如果要导出所有的别名,则需要调用Export-Alias cmdlet,最简化的情况下只需提供保存别名的位置即可。导出的别名文件为文本格式,具体操作方法如下:

PS C:\> Export-Alias aliases.txt
PS C:\> type .\aliases.txt
# Alias File
# Exported by : Administrator
# Date/Time : 2008年12月3日 14:32:19
# Machine : NULL
"ac","Add-Content","","ReadOnly, AllScope"
"asnp","Add-PSSnapIn","","ReadOnly, AllScope"
"clc","Clear-Content","","ReadOnly, AllScope"
"cli","Clear-Item","","ReadOnly, AllScope"
"clp","Clear-ItemProperty","","ReadOnly, AllScope"
"clv","Clear-Variable","","ReadOnly, AllScope"
"compare","Compare-Object","","ReadOnly, AllScope"
"cpi","Copy-Item","","ReadOnly, AllScope"
"cpp","Copy-ItemProperty","","ReadOnly, AllScope"
"cvpa","Convert-Path","","ReadOnly, AllScope"
"clear","Clear-Host","","AllScope"
.......

导入的过程需要调用Import-Alias cmdlet将导出的别名文件安装到目标主机的当前Shell进程中,如:

PS C:\> Import-Alias .\aliases.txt
Import-Alias : Alias not allowed because an alias with the name 'ac' already ex
ists.
At line:1 char:13
+ Import-Alias <<<<  .\aliases.txt
    + CategoryInfo          : ResourceExists: (ac:String) [Import-Alias], Sess
   ionStateException
    + FullyQualifiedErrorId : AliasAlreadyExists,Microsoft.PowerShell.Commands
   .ImportAliasCommand

Import-Alias : Alias not allowed because an alias with the name 'asnp' already
exists.
At line:1 char:13
+ Import-Alias <<<<  .\aliases.txt
    + CategoryInfo          : ResourceExists: (asnp:String) [Import-Alias], Se
   ssionStateException
    + FullyQualifiedErrorId : AliasAlreadyExists,Microsoft.PowerShell.Commands
   .ImportAliasCommand

Import-Alias : Alias not allowed because an alias with the name 'clc' already e
xists.
At line:1 char:13
+ Import-Alias <<<<  .\aliases.txt
    + CategoryInfo          : ResourceExists: (clc:String) [Import-Alias], Ses
   sionStateException
    + FullyQualifiedErrorId : AliasAlreadyExists,Microsoft.PowerShell.Commands
   .ImportAliasCommand

在本机执行该操作时,会抛出大量的错误。默认情况下Export-Alias cmdlet会导出所有的别名,甚至包括内置的别名。为了保证在导入别名的过程中不覆盖用户的配置,Import-Alias会对覆盖别名的操作抛出警告信息。这不是一个问题,因为内置的别名定义在任何机器上都是一致的,可以不会造成错误。

有时需要强制覆盖已经存在的别名,可以通过为Import-Alias cmdlet传递-Force参数实现,操作如下例所示:

PS C:\PowerShell> Import-Alias .\aliases.txt -Force
PS C:\PowerShell>

如果不覆盖内置的别名,只导入新增的别名,可以通过指定ErrorAction参数为SilentlyContinue来忽略错误提示。这样不会覆盖已有别名,而只添加新增的别名,操作方法如下所示:

PS C:\PowerShell> Import-Alias .\aliases.txt -ErrorAction SilentlyContinue
PS C:\PowerShell>

也可以通过编辑已导出的别名文件,清除其中内置的别名的方式来实现只导入新增别名。然而这不是好方法,因为导出的别名文件有很多行,清理并不方便。可以通过指定过滤器的方式只导出部分别名,如下例只导出以log开头的别名:

PS C:\PowerShell> Set-Alias log-host Write-Host
PS C:\PowerShell> Set-Alias log-verbose Write-Verbose
PS C:\PowerShell> Export-Alias log-aliases.txt log*
PS C:\PowerShell> type .\log-aliases.txt
# Alias File
# Exported by : Administrator
# Date/Time : 2008年12月3日 14:58:58
# Machine : NULL
"log-host","Write-Host","","None"
"log-verbose","Write-Verbose","","None"

甚至可以分多次将别名导出,并添加到相同的文件中。下例将trace*的别名导入到之前的别名列表中:

PS C:\PowerShell> Set-Alias trace-host Write-Host
PS C:\PowerShell> Export-Alias .\log-aliases.txt trace* -append
PS C:\PowerShell> type .\log-aliases.txt
# Alias File
# Exported by : Administrator
# Date/Time : 2008年12月3日 14:58:58
# Machine : NULL
"log-host","Write-Host","","None"
"log-verbose","Write-Verbose","","None"
# Alias File
# Exported by : Administrator
# Date/Time : 2008年12月3日 15:05:45
# Machine : NULL
"trace-host","Write-Host","","None"

能够看到其中的文件头被插入了两次,但是无关紧要,在导入过程中会忽略注释的内容。

如果需要将别名导出为脚本形式,便于后面通过执行方式导入,只需要添加-as参数即可。如下所示:

PS C:\PowerShell> Export-Alias log-aliases.ps1 log* -as Script
PS C:\PowerShell> type .\log-aliases.ps1
# Alias File
# Exported by : Administrator
# Date/Time : 2008年12月3日 15:16:51
# Machine : NULL
set-alias -Name:"log-host" -Value:"Write-Host" -Description:"" -Option:"None"
set-alias -Name:"log-verbose" -Value:"Write-Verbose" -Description:"" -Option:"N
one"
PS C:\PowerShell>

也可以通过指定文件格式为csv,将别名导出为用逗号分隔的文件,这样即可通过Microsoft Word打开。如:

PS C:\PowerShell> Export-Alias .\log-aliases.csv log* -as csv
PS C:\PowerShell> type .\log-aliases.csv
# Alias File
# Exported by : Administrator
# Date/Time : 2008年12月3日 15:25:56
# Machine : NULL
"log-host","Write-Host","","None"
"log-verbose","Write-Verbose","","None"
PS C:\PowerShell>

别名与变量及函数相似,在当前Shell进程中定义的别名仅在当前进程中有效。如果需要使别名在所有的控制台上均有效,则需要保存别名的配置。保存的方式如下:

(1)在配置文件中添加Set-Alias命令定义自己的别名。如果要修改配置文件,则需要学习第13章中的有关内容。只需要将配置的命令粘贴到配置文件中即可实现别名的重复使用,但这种做法会导致配置文件的维护很不方便。

(2)在定义别名后将其导出到特定文件中,然后编辑文件以清除其中无用的别名。将修改后的文件保存在特定的位置,通过Import-Alias命令把该文件导入到配置文件中。这种做法的好处在于可以很方便地维护别名,最好将别名文件保存在配置文件目录下,以避免无意中删除别名配置文件。

总 结

本文着重介绍了如何定义和使用别名来使日常的Shell使用更加便捷。键入 cmdlet 名称很麻烦,为最大限度地减少键入内容并使习惯其他外壳程序的用户更容易使用,PowerShell 支持别名(即命令的替代名称)的概念。可以为 cmdlet 名、函数名或可执行文件名创建别名,然后在任何命令中键入别名。

赛迪网地址:http://news.ccidnet.com/art/32857/20100617/2089265_1.html

作者: 付海军

版权:本文版权归作者所有

转载:欢迎转载,为了保存作者的创作热情,请按要求【转载】,谢谢

要求:未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任

个人网站: http://txj.shell.tor.hu/


发表回复