PowerShell 和 CMD 是 Windows 上绕不开的两个终端,尤其当你开始接触 Git、conda、Docker、Python 这类工具时,几乎每天都要和命令行打交道。但很多新手第一次打开“终端”时都会困惑:为什么网上教程里写的是 CMD,自己电脑默认打开却是 PowerShell?为什么同一条指令在 CMD 里能跑,粘到 PowerShell 里就报错?甚至有人以为是系统坏了,重装完发现还是一样。这类问题的根源并不是命令本身错了,而是你没搞清楚当前“这个终端到底是谁”。这篇文章就把 PowerShell 与 CMD 常用指令之间的差异完整梳理一遍,重点放避坑:路径、参数、脚本、执行策略、常见报错,哪一步容易翻车就拆哪一步。适合刚开始接触命令行、第一次写 .bat 或 .ps1、想把 Windows 自动化脚本跑起来的同学参考。
我尽量少讲虚的,所有案例都来自日常操作里能直接复现的场景。你不需要全部背下来,把这篇文章当作查表工具用就行,遇到问题再回来翻对应章节。
1. CMD 和 PowerShell 的区别,别只看表面
1.1 CMD:从 DOS 时代传下来的“文本处理管线”
CMD 即 cmd.exe,是 Windows 自带的命令解释器,直接继承了 DOS 时代的交互方式和批处理习惯。它最显著的特征就是:启动快、轻量、到处都有。不管多老的 Windows 版本都能打开,.bat 和 .cmd 脚本至今仍被软件安装包、系统运维脚本大量使用,很多部署工具在 Windows 上默认调用的还是 CMD。
但 CMD 的底层模型是文本。它看到的世界就是一串字符流:执行一条命令,得到一段格式化文本;想从结果里取某个字段,就得用 findstr、for /f 这类“文本加工厂”去二次解析。比如你想知道 8080 端口被哪个进程占用了,CMD 的做法是给你打印一整张表,然后你自己人眼去找,或者用 findstr 过滤出包含 8080 的那一行,再对着表头逐列数第几个数字是 PID。这种思路在几十年前没问题,但放到今天的自动化场景里确实很吃力。
CMD 的另一个特点是脚本语法简陋。变量用 %var% 包裹,if/for 的写法极其反直觉,循环里还不能直接用管道处理复杂的对象数据。写个稍微复杂点的批处理,基本就是在和字符串转义、行尾空格、编码乱码作斗争。对新手来说,CMD 的入门门槛低,但一旦需求超过“敲两行命令查信息”的范围,就会迅速变得折磨人。
1.2 PowerShell:以对象为单位的现代命令行环境
PowerShell 是微软基于 .NET 重新设计的命令行环境和脚本语言,它的命令叫 cmdlet,命名规则是“动词-名词”,比如 Get-Process、Get-Service、Set-ExecutionPolicy。PowerShell 最大的变化不是多了几百个命令,而是管道的传输单位变了:管道里不再流动文本,而是流动对象。
这句话怎么理解?以列目录为例。CMD 的 dir 输出是一段排版好的文本,文件名、大小、日期等信息被格式化成了人眼看起来整齐的表格,但后续程序想再拿这些数据去做处理,就得靠文本切割,非常脆弱。而 PowerShell 的 Get-ChildItem 会把每个文件都变成一个对象,每个对象自带 Name、FullName、Length、LastWriteTime 等属性。你可以把结果直接传给 Where-Object 做筛选、传给 Sort-Object 做排序、传给 Select-Object 挑自己关注的列,最后输出只是一层“展示壳”,底层数据全程都是结构化的。
也正因为对象化,PowerShell 的语法复杂度明显比 CMD 高。变量、管道、作用域、错误处理、模块导入、远程管理……学习曲线会陡一些。但换来的是脚本能力的质变,尤其是批量处理文件、操作注册表、管理系统服务、对接 .NET
