PowerShell Docs
PowerShell Docs
无法加载文件,因为在此系统上禁止运行脚本
1 | get-executionpolicy # 获取当前执行策略 |
[!info] 执行策略
Restricted
执行策略 (默认设置) 不允许任何脚本运行。
AllSigned
和RemoteSigned
执行策略可防止 Windows PowerShell 运行没有数字签名的脚本。
高级特性
不清楚具体是哪个版本开始,power shell 具有了自动补全的功能,我还以为是 starship 带来的呢 hhhh
在输入重复指令时,可以看见提示信息以灰色字体出现在当前光标后方,按右箭头键即可自动补全。
按下 F2
,可以查看不同完成建议的列表,通过上下箭头选中,回车上屏。
按照 reddit 的说法,该功能是巨硬合并了 PSReadline
模块后带来的。
概念
PowerShell 命令称为 cmdlet(读作 command-let)。除了 cmdlet 外,使用 PowerShell 还可以在系统上运行任何可用命令。
PowerShell 使用 “动词 - 名词” 名称对来命名 cmdlet。例如,PowerShell 中包含的 Get-Command
cmdlet 用于获取在命令行界面中注册的所有 cmdlet。谓词标识 cmdlet 执行的操作,名词标识该 cmdlet 执行其操作的所在资源。
谓词
谓词是 PowerShell 中的一个重要概念。它是大多数 cmdlet 都遵循的一种命名标准。你在编写自己的命令时,也应遵循此命名标准。其中的思路是,谓词表示你尝试执行的操作,例如读取数据或更改数据。 PowerShell 有一个标准化的谓词列表。要获取所有可用谓词的完整列表,请使用 Get-Verb
cmdlet:
1 | PS F:\> get-verb |
环境变量的用法
不同于 Linux 的直接使用 $key
,powershell 中必须加上 $env:
的前缀
1 | $env:your_env |
Get-Member 发现对象、属性和方法
1 | # 获取当前路径下所有vtt字幕文件 |
Get-Command 查找命令
Get-Command
cmdlet 将返回系统上安装的所有可用命令的列表,包含四个属性字段
根据名称筛选
1 | # 查找名为Get-Process的命令 |
根据名词和谓词进行筛选
1 | # 根据谓词筛选:查找名为 "Get-xxx" 的命令 |
使用其他 Cmdlet 筛选结果
Select-Object
此通用命令可帮助你从一个或多个对象中选取特定属性。还可以限制返回的项目数。
1 | # 返回当前会话中前 5 个可用命令的 Name 和 Source 属性值 |
文件 IO
创建文本文件
1 | # 创建 |
清空文件内容
1 | Clear-Content .\shell_test\text.txt |
插入文件内容
1 | Set-Content .\shell_test\text.txt 'hello' |
结果为
1 | hello |
看起来是会自动写入换行符
文件和文件夹
New-Item cmdlet 用于通过使用 -Path
作为文件路径和 -ItemType
作为文件传递路径来创建文件。
创建
创建文件夹:在 F:\
下创建 shell_test
文件夹
1 | New-Item -Path 'F:\shell_test' -ItemType Directory |
创建文件:在 F:\shell_test
下创建 test.txt
文件
1 | New-Item -Path 'F:\shell_test\test.txt' -ItemType File |
复制
Copy-Item cmdlet 用于通过传递要复制的目录/文件的路径和目标路径来复制目录。
复制文件夹
1 | Copy-Item 'F:\shell_test\' 'F:\copy_shell_test' |
递归复制文件夹(包含里面的内容)
1 | Copy-Item 'F:\shell_test\' -Recurse 'F:\copy_shell_test' |
复制指定的内容
1 | Copy-Item -Filter *.jpg -Path 'F:\shell_test\' -Recurse 'F:\copy_shell_test' |
删除
Remove-Item cmdlet 用于通过传递要删除的目录/文件的路径来删除。
1 | # 删除文件 |
当删除文件夹不为空时,会提示
1 | Confirm |
因此,可以递归删除文件夹
1 | # 删除 shell_test 及其目录下所有内容 |
移动
Move-Item cmdlet 用于通过传递要移动的目录/文件的路径和目标路径来移动目录。
1 | # 移动单个文件 |
注意两个问题:
- 不涉及复杂参数的情况下,路径参数的引号可以不加
F:\shell_test\2
路径下的文件也会被移动- 移动多个文件时,如果省略
-Destination
,则最后一个路径默认作为目的地 - 移动命令没有
-Recurse
一说 -Force
参数可以强制运行命令而不要求用户确认。
重命名
Rename-Item cmdlet 用于通过传递要重命名的文件 (夹) 的路径和目标名称来重命名文件 (夹)。
1 | # 将 1 重命名为 this1 |
需注意,同路径下不可以有同名文件夹,否则会失败。
检测是否存在
Test-Path cmdlet 用于检查文件 (夹) 是否存在。
1 | Test-Path 'F:\shell_test\' |
结果为
1 | 1 |
Measure-Object
Measure-Object cmdlet 可用于获取传递的输出的属性,例如最小值、最大值、大小、计数、行等。
1 | # 获取文件属性 |
结果为(行数、单词数、字符数)
1 | Lines Words Characters Property |
统计目录下文件数量
1 | Get-ChildItem .\shell_test\ | Measure-Object |
表示共有 3 个文件(文件 + 文件夹)
1 | Count : 3 |
也可以如下操作:
1 | $zips = Get-ChildItem *.zip |
比较运算符
等式
-eq
、-ieq
、-ceq
- 等于-ne
、-ine
、-cne
- 不等于-gt
、-igt
、-cgt
- 大于-ge
、-ige
、-cge
- 大于或等于-lt
、-ilt
、-clt
- 小于-le
、-ile
、-cle
- 小于或等于
匹配
-like
、-ilike
、-clike
- 字符串匹配通配符模式-notlike
、-inotlike
、-cnotlike
- 字符串与通配符模式不匹配-match
、-imatch
、-cmatch
- 字符串匹配正则表达式模式-notmatch
、-inotmatch
、-cnotmatch
- 字符串与正则表达式模式不匹配
替代功能
-replace
,-ireplace
,-creplace
- 替换与正则表达式模式匹配的字符串
包含
-contains
、-icontains
、-ccontains
- 集合包含值-notcontains
、-inotcontains
、-cnotcontains
- 集合不包含值-in
- 值位于集合中-notin
- 值不在集合中
类型
-is
- 这两个对象的类型相同-isnot
- 对象类型不相同
Alias
内置别名
1 | Get-Alias |
[!tip]
ls
,pwd
,cd
等指令在 power shell 仍然能够工作,就是得益于内置的 alias
为无参 cmdlet 创建 alias
1 | # 将Get-AuthenticodeSignature创建别名gas |
若要更改或删除只读别名,请使用 Force
参数。
为有参命令创建 alias
不能为带有参数和值的命令(例如 Set-Location -Path C:\Windows\System32
)创建别名。若要为某个命令创建别名,请创建一个包括该命令的函数,然后为此函数创建别名。
1 | Function CD32 {Set-Location -Path C:\Windows\System32} |
重定向输出
Out-File
将 powershell 的输出写入到文件。
1 | # 直接写入 |
以 ASCII 格式将输出发送到文件:
1 | $Procs = Get-Process |
Encoding
参数将输出转换为 ASCII 格式-Width
参数将文件中的每一行限制为 50 个字符,因此某些数据可能会被截断。
关于异常
终止和非终止错误:异常通常是终止错误。引发的异常要么被捕获要么会终止当前执行程序。
默认情况下,
Write-Error
会生成一个非终止错误,并将错误添加到输出流,而不引发异常。也就是说,Write-Error
和其他非终止错误不会触发catch
!
创建异常
若要创建自己的异常事件,可以使用 throw
关键字引发异常。
1 | function Start-Something |
前面提到过,默认情况下 Write-Error
不会引发终止错误。但如果指定 -ErrorAction Stop
,Write-Error
将会生成一个可使用 catch
处理的终止错误。
1 | Write-Error -Message "Houston, we have a problem." -ErrorAction Stop |
创建类型异常
1 | throw [System.IO.FileNotFoundException] "Could not find: $path" |
try/catch/finally
PowerShell(以及许多其他语言)中的异常处理方式是,先对一部分代码执行 try
,如果引发终止错误,则对其执行 catch
。可使用 $_
变量访问 catch
块中的异常信息。
1 | try |
有时不需要处理错误,但无论异常是否发生,仍需要执行一些代码,则使用 finally
。
处理异常
捕获类型化异常
1 | try |
脚本模块
将可复用的函数单独封装进 psm1
模块文件,然后引用
1 | # common.psm1 |
然后在其他 ps1
文件中引入该模块
1 | # script.ps1 |
由于自定义函数/模块的名称未必严格符合 powershell 的 verb
格式,有时会报 warning,通常加上 -DisableNameChecking
忽略即可。
输出流
在 PowerShell 中,你可以使用 Write-Host
命令输出内容,并且可以通过修改输出的字体颜色和背景色来增加可读性。你可以使用 -ForegroundColor
和 -BackgroundColor
参数来设置文本的前景色(字体颜色)和背景色。此外,你也可以使用 \n
来添加换行符。
1 | # 输出红色文本 |
函数
函数参数 使用 param()
声明,可以在声明时指定参数类型。
1 | function Validate-Path { |
$input
是一个关键字,不可以作为参数使用。
函数返回值有多种形式:
-
返回包含多个值的数组
1
return @($i, $o, $f)
返回值的获取
1
2$params = func
Write-Host $params[0] # 使用索引获取 -
返回
key-value
形式的哈希表1
2
3
4
5return @{
key1 = $i
key2 = $o
key3 = $f
}返回值的获取
1
2$params = func
Write-Host $params.key1 # .key获取
执行默认操作
Invoke-Item
用于对指定项执行默认操作。例如在与某一文档文件类型关联的应用程序中打开该文档文件。
打开文件
1 | Invoke-Item "C:\Test\a.doc" |
在文件资源管理器打开当前路径
1 | Invoke-Item . |
路径拼接
网络
DNS
可以使用 Resolve-DnsName
cmdlet 来测试一个 URL 的 DNS 查询记录。
1 | Resolve-DnsName example.com [-Type MX] [-Server 8.8.8.8] |
- 使用
-Type
参数指定要查询的 DNS 类型 - 使用
-Server
参数指定要使用的 DNS 服务器
1 | Get-DnsClientServerAddress |
这将显示操作系统当前配置的 DNS 服务器地址。通常情况下,你会看到一个或多个 DNS 服务器的 IP 地址。
路由表 Route
Get-NetRoute
Windows 路由表控制有一个内置命令 route
,大概率是从 cmd 继承过来的。
1 | # 打印路由表 |
route print
打印出的路由表和 powershell Get-NetRoute
cmdlet 打印的结果稍有不同。如下:
1 | route print |
可以看见,主要区别在于 powershell 默认使用了 IP-CIDR 格式,因此相比于 route 命令缺少了子网掩码字段。
New-NetRoute
1 | # 向路由表添加 IP |
注意,不同于
route add
,Net-NetRoute
的子网掩码用 IP-CIDR 格式表示。
参数 | 作用 | 默认 |
---|---|---|
AddressFamily | IPv4/IPv6 |
自适应其余参数 |
Confirm | 执行前确认 | False |
InterfaceAlias | 网卡名称 | None |
PolicyStore | ActiveStore/PersistentStore |
两个都有 |
注意,不声明 PolicyStore 的情况下,会插入永久路由!
硬件相关
磁盘
1 | # 常用于查看 MediaType (HDD 还是 SDD) |
管理服务 Service
获取服务
1 | Get-Service |
- 不带参数将返回所有服务(
Status / Name / DisplayName
) - 可以添加参数(如
-Name
)进行筛选,支持通配符过滤或提供显示名称的列表
服务的
Name
和DisplayName
并不总是一致!
有时服务的字段过长,导致终端中的输出被截取,可以通过 Format-Table
解决:
1 | Get-Service -name razer* | Format-Table -AutoSize |
获取必需和从属服务
1 | # 获取 LanmanWorkstation 服务所依赖的服务。 |
停止、启动、暂停和重启服务
1 | # 停止服务 |
设置服务属性
Set-Service
cmdlet 更改服务的属性,也可以启动、停止或暂停服务。
更改显示名称
1 | Set-Service -Name LanmanWorkstation -DisplayName "LanMan Workstation" |
更改服务的启动类型
1 | Set-Service -Name BITS -StartupType Automatic |
- Automatic - 服务将由操作系统在系统启动时启动或在系统启动时已启动。 如果自动启动的服务依赖于手动启动的服务,则手动启动的服务也会在系统启动时自动启动。
- AutomaticDelayedStart - 系统启动后不久启(延迟启动)。
- Disabled - 服务被禁用,不能由用户或应用程序启动。
- InvalidValue - 不起作用。 该 cmdlet 不返回错误,但服务的 StartupType 不会更改。
- Manual - 服务只能由用户(使用服务控制管理器)或应用程序手动启动。
更改服务的说明
1 | # 查看 ipreport 服务当前 Description |
处理多个服务
Set-Service
cmdlet 一次只接受一个服务名称。 但是,可以通过管道将多个服务传递给 Set-Service
,以更改多个服务的配置。
1 | Get-Service SQLWriter,spooler | |
删除服务
1 | # 移除名为 TestService 的服务 |
使用 -confirm
参数可以在运行 cmdlet 之前进行确认。
案例
如何调用已有脚本实现代码复用?
可以通过循环,在每次迭代中调用脚本。下面是一个示例代码,演示了如何在 PowerShell 中循环调用脚本来处理多个输入文件:
1 | # 假设有一个包含多个输入文件的文件夹,路径为 $inputFolder |