Windows折腾记之PowerShell 7

文章目录

什么是PowerShell

PowerShell可以理解为Cmd的升级版,但别看这样,PowerShell可是能与bash、zsh等顶级Shell相媲美的。其简洁美丽的语法,是Cmd远远所不及的。同样,PowerShell还可以无缝调用.NET Core。而面向对象,则是PowerShell最大的优点。

以下文段摘自《Windows 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_emacs

function的作用就类似于别名,其实下面这段代码也可以实现同样的功能:

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好一些。

发表评论

滚动至顶部