文本进、文本出:搞垮上千个批处理的硬伤
cmd是个文本shell:dir打印出排版好的列,而你真正想要的东西——大小、日期、文件名——全是以字符形式粘在页面上,随后还得自己裁开。建立在这种解析之上的脚本,一旦某个区域设置的月份写法变了、某列变宽了、文件名里带了个空格,当天就崩。维护过批处理文件的人都记得那套仪式:FOR /F配tokens和delimiters,默念一句祈祷,再给用另一种语言应答的机器准备第二版脚本。
PowerShell于2006年发布、构建在.NET之上,设计初衷正是终结这一切。Get-ChildItem不打印行——它返回FileInfo对象,把Name、Length、LastWriteTime和Extension当作数据随身携带。命令之间的管道把这些对象完整传下去,所以在上海写好的过滤器到了慕尼黑也一字不差地运行;总和是一个可以四舍五入、可以格式化的数字,而不是只能盲信的字符串。
动词-名词cmdlet:清理工具该有的组合方式
这里的命令都是“动词-名词”命名的cmdlet——Get-ChildItem、Where-Object、Measure-Object、Remove-Item——而这份纪律绝非摆样子:获批准的动词能让管道在半年后依然可读,就像贴了标签的工具箱胜过塞满神秘螺丝刀的抽屉。做清理时,组合比任何单个命令都重要:查找、过滤、统计、删除是一条对象流,而不是四大段批处理语法。每个阶段都会自报家门,所以匆匆写下的一行命令,一个月后读起来仍像一句话。
更安静的优势是安全。Remove-Item接受-WhatIf——打印出它将执行的每一次删除,然后一次也不执行;还接受-Confirm——一个文件一个文件地询问。这是cmd从未有过的干跑。Get-AppxPackage可以直接管道到Remove-AppxPackage,卸载预装应用成了一条管道,而不是一场注册表狩猎。这不会让删除变得无害,但让它变得可检视——而这正是清理脚本一直缺的那件东西。
- Get-ChildItem $env:TEMP -Recurse — 每个文件对应一个FileInfo对象,Length和LastWriteTime都是现成数据
- Where-Object Length -gt 100MB — 作用于对象的过滤,不受区域设置和列宽影响
- Measure-Object Length -Sum — 以GB计的总量是个数字,不是要再解析一遍的字符串
- Remove-Item ... -WhatIf — 一次干跑,列出它将执行的每一次删除
- Get-AppxPackage *zune* | Remove-AppxPackage — 一条管道搞定appx卸载
cmd仍占上风的地方,以及诚实的局限
PowerShell并非没有代价。它比cmd启动慢;执行策略会拦住那些在运行Set-ExecutionPolicy -Scope CurrentUser RemoteSigned之前就执行下载来的.ps1的新手;而对整个磁盘做递归Get-ChildItem,在专用扫描器旁边只能算爬行。至于那些经典命令——ipconfig、sfc、powercfg——cmd依然是更轻的窗口,本文没有任何内容会让那二十条命令退休。
另一个诚实的局限是并发:删除跑在单线程上,一棵塞满小文件的巨大目录树该花多久就得花多久。但天平依然清晰。对一切先测量、先过滤、先报告再删除的工作,PowerShell把你的系统当作数据,而不是一块等着刮取的屏幕——而且我们后续文章里的一行命令,只需要复制粘贴。
常见问题与解答
清理Windows时PowerShell比cmd更好用吗?
凡涉及过滤、统计或删除前干跑的活儿,是的:对象管道在任何区域设置下都能存活,并会在行动前先报告。至于网络和修复的经典命令——ipconfig、sfc、chkdsk——cmd仍是更轻的窗口。
Windows PowerShell和PowerShell 7有什么区别?
Windows PowerShell 5.1随系统附带,跑在.NET Framework上;PowerShell 7是需要单独安装的跨平台继任者。清理用的一行命令在两者中原样可跑。
继续阅读
联系我们: [email protected]