文章目录
什么是PowerShell
PowerShell可以理解为Cmd的升级版,但别看这样,PowerShell可是能与bash、zsh等顶级Shell相媲美的。其简洁美丽的语法,是Cmd远远所不及的。同样,PowerShell还可以无缝调用.NET Core。而面向对象,则是PowerShell最大的优点。
Linux的设计思想决定所有的输入和输出都尽可能是文本格式,这样可以方便各进程间的合作。同样这也要求各个程序提供一定强度的文本解析能力。但Windows的思想与此不同,PowerShell中很多输入输出都不是普通的文本(plain text),而是一个个对象(objects)。因此与其说PowerShell是一种交互环境,不如说它是一种强大语言的Runtime,而这种语言甚至是面向对象的。
但是,PowerShell的不足也有很多,如练习成本大、较为复杂等。而且,有一些系统命令在Cmd下能够正常运行,但在PowerShell下却不行(如用sc命令创建系统服务,在Cmd下可以使用,但在PowerShell下却会出问题)。
PowerShell 7
简介
PowerShell 7是PowerShell的最新升级版,而一般Windows内置的版本都是PowerShell 5。PowerShell 7(以下简称“PS7”)最直观的两个新特性就是新的运算符和全平台通用性,也就是说在Mac和Linux上也能使用PowerShell。有关PS7新特性的内容,请参考《PowerShell 7.0 正式发布》。
下载与安装
PS7没有内置,应用商店里也没有,所以我们需要手动下载安装。下载地址:Latest Release of PowerShell,这也是一个开源的GitHub项目。从中选择合适的版本(我的电脑是Windows,64位,处理器是英特尔的,写本文时最新版本是v7.0.3,所以选择的是“PowerShell-7.0.3-win-x64.msi”),下载后直接安装即可。安装完成后,可以打开试验一下——输入以下代码:
$PSVersionTable
如果输出以下内容,即为安装成功。
Name Value
---- -----
PSVersion 7.0.3
PSEdition Core
GitCommitId 7.0.3
OS Microsoft Windows 10.0.18363
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0注:版本号会随版本更新而变化,所以不必完全一致,只要“PSVersion”的内容以“7”开头即可。
配置PS7的PROFILE
注:此步骤非必做,可跳过,且不光对PS7有效,对所有版本的PowerShell都有效。
PowerShell有一个PROFILE文件,每次打开PowerShell时都会先执行一遍这里面的内容,相当于Cmd时代编辑注册表指定自动运行的那个文件。那么如何编辑PROFILE呢?首先我们先执行以下命令(注:大小写不要求,下同):
$PROFILE
如果输出为false,则代表还没有PROFILE文件,执行下一步;如果输出不是false,则跳过下一步,执行第三步。
第二步(第一步输出为false才执行),输入以下代码创建PROFILE文件:
New-item -type file -force $profile
第三步,开始编辑PROFILE文件,输入以下代码:
notepad $PROFILE
执行命令后会新建一个记事本窗口打开PROFILE文件,在里面编辑即可。
注:并不是一定要使用记事本打开,比如我想使用一个叫做Notepad++的编辑器打开,那么首先把它的路径添加到Path中,然后执行以下代码:
notepad++ $PROFILE
同理,如果要使用其他编辑器的话直接把notepad替换即可,比如要使用VSCode的话就输入:
code $PROFILE
这个PROFILE文件通常是用来添加别名的。至于如何添加别名,请参见以下代码,在PROFILE文件中编写即可:
Set-Alias -Name 别名 -Value 本名 # 或 Set-Alias 别名 本名 # 皆可
比如我安装了PuTTY作为我的SSH工具,但是PuTTY的命令行工具名字为“putty.exe”,而不是“ssh”,这时候就可以输入以下代码:
Set-Alias ssh putty.exe
保存文件,在命令窗口中输入
. $PROFILE
即可使PROFILE文件生效,此后可以直接使用ssh XXX@XXX.XXX.XXX来代替putty.exe XXX@XXX.XXX.XXX。
不过,如果要别名一些带有参数的东东,你会发现PowerShell会出现错误,因为Set-Alias不能别名带有空格的东西。比如说:
# 错误示范 Set-Alias -Name emacs -Value emacs-26.2.exe -nw
这段代码的意图是在命令行内打开emacs而不是弹出窗口,只不过PROFILE会无法运行。以下是正确示范:
# 正确示范
function fun_emacs {
emacs-26.2.exe -nw
}
Set-Alias emacs fun_emacsfunction的作用就类似于别名,其实下面这段代码也可以实现同样的功能:
function emacs {
emacs-26.2.exe -nw
}现在,输入“. $PROFILE”,试验一下你的别名吧!然后你会发现,它们无法正常使用:它们能够正常打开,但是却不会理会你输入的想要编辑的文件名。如果要添加参数的话,请使用“$args”,下面是修改后的代码:
function fun_ssh {
putty.exe $args
}
Set-Alias ssh fun_ssh
function fun_emacs {
emacs-26.2.exe -nw $args
}
Set-Alias emacs fun_emacs现在,这部分就没问题了。
那么,有的童鞋就要这样问了:“我按照你的方法做了,为什么我还是出错了啊!”其实,这种问题是由你所别名的程序路径里带有空格所导致的。比如说:
#错误示范
function fun_test {
"D:\Program Files\Test\test.exe" $args
}
Set-Alias test fun_test像这样的代码,程序路径也用引号括起来了,似乎没什么问题,但是运行就是会出错,这是为什么呢?答案就是······我也不知道-_-但是我知道怎么去解决,那就是在程序路径前面加上一个“& ”就可以了,至于为什么······我也不太了解-_-
# 正确示范
function fun_test {
& "D:\Program Files\Test\test.exe" $args
}
Set-Alias test fun_test这些都是一些小儿科的东西,有没有更高难度的东西?
我是一名OIer,在刷题的时候我要经常进入我本地的刷题目录,然而这是一个十分复杂的目录,每一次都手打极其麻烦,这可以通过别名来实现:
# 刷题目录:F:\programming\learning\XXX\XXX\XXX\XXX\刷题
function fun_cpd {
F:
cd F:\programming\learning\XXX\XXX\XXX\XXX\刷题
}
Set-Alias cpd fun_cpd这段代码的作用是进入F盘,然后进入目录。也就是说,以后输入“cpd”即可进入“F:\programming\learning\XXX\XXX\XXX\XXX\刷题”这样一个复杂的目录。不过,这怎么能满足我们的需求呢?我在刷题的时候经常要在“刷题”目录下建一些题目的子文件夹,如“P1000”文件夹。以下为我们要实现的功能:
- 能够接受参数:我们要用到的子目录
- 判断子目录是否存在,如果存在则直接进入,不存在则创建目录,并创建“子目录名称.cpp”文件
下面直接贴一下代码:
function fun_cpd {
F:
# 判断名为“$args”的子目录是否存在,如果存在则直接进入,不存在则创建目录,并创建“${args}.cpp”文件
if (Test-Path F:\programming\learning\XXX\XXX\XXX\XXX\刷题\$args) {
cd F:\programming\learning\XXX\XXX\XXX\XXX\刷题\$args # 存在,则直接进入
} else {
cd F:\programming\learning\XXX\XXX\XXX\XXX\刷题 # 进入父目录
mkdir $args # 创建子目录
cd F:\programming\learning\XXX\XXX\XXX\XXX\刷题\$args # 进入子目录
New-Item "${args}.cpp" -type file # 创建名为“${args}.cpp”的文件
}
}
Set-Alias cpd fun_cpd这段代码中出现的新东西是“Test-Path”、“mkdir”和“New-Item”。“Test-Path”的功能强大,其中的一个功能是判断目录是否存在,也就是我们现在要用的功能;“mkdir”的作用是创建一个新目录;“New-Item”之前在创建PROFILE时已经碰过了面,“-type file”的作用是表示要创建文件而不是其他的东西。还有if-else语句,这就不用我多赘述了。值得注意的一个点是,将“${args}.cpp”改为“$args.cpp”似乎会无法运行,我也不是很清楚,不过“${args}.cpp”是100%准确的。
现在,我们已经实现了相当强大的功能了。什么,还想要更复杂的?那个······抱歉哈,我也不是学这个的,再复杂的我也不会了(汗
PS7搭配Windows Terminal
在之前的一篇文章中(《Windows折腾记之Windows Terminal配置》),我提到了WT的配置。在WT默认的设置文件中,你大概会找到这样一段代码:
{
// Make changes here to the powershell.exe profile.
"guid": "{不用管这里}",
"name": "Windows PowerShell",
"commandline": "powershell.exe",
"hidden": false
},通过在WT的PowerShell内执行$PSVersionTable,我们可以了解到这个PowerShell是PowerShell 5。那么怎么把它替换成PS7呢?
PS7为了和5作区分,将自己的可执行文件的文件名改为了“pwsh.exe”。也就是说,只要将以上代码小小地修改一下即可。
{
// Make changes here to the powershell.exe profile.
"guid": "{不用管这里}",
"name": "Windows PowerShell",
"commandline": "pwsh.exe",
"hidden": false
},可以执行“$PSVersionTable”试验一下,看是不是已经被替换为了PS7。
总结
PowerShell无疑是一个非常好用、强大的Shell,但其学习成本却远比bash等语言要高,原因是它的面向对象式编程套在一个脚本语言上却显得过于臃肿了,且用到的场景比较少。总之,还是推荐大家用的,只不过不要太费力去学习,需要用的时候就上网查一下如何使用即可。
至于升级到PS7这件事,如果你是使用PowerShell开发的程序员、或是PowerShell的死忠粉,那么还是推荐升级的,因为PS7不仅支持多平台,而且还有许多很有用的优化;如果你只是一个普通的Windows用户,连PowerShell和Cmd具体有什么区别都搞不太清楚,那么就不用升级了,一方面升级还是有点麻烦的,另一方面升级了也没有什么具体的用处,其实WT+Cmd的组合就足以胜任平常的日常生活,既好看又易用,只是Cmd的语法又偏僻又恶心,要开发的话还是使用PowerShell好一些。
