目录

一、核心定义(先理清各自是什么)

二、它们之间的“血缘与阶层”关系(重点)

三、一张表看懂本质区别(命令语法 + 底层逻辑)

四、为什么 Linux 世界里“Shell”几乎等同于“Bash”?

五、举几个例子,帮你“对号入座”

💡 一句话终极总结

番外:如何在 Windows 上安装 WSL(Windows Subsystem for Linux)

附:关于“环境变量”的问题


很多人会问到shell、bash、cmd之间到底是什么关系,那恭喜你,这个问题你问到了操作系统的根基。为了让大家彻底分清,我用“语言、翻译官、方言”的比喻来讲,再加上一张对比表,你会发现它们的关系其实非常清晰。

先说一句核心结论:Shell 是“翻译官”这个职业,Bash 和 CMD 是两位具体的“翻译官”,且 Bash 翻译得更好、更强大。


一、核心定义(先理清各自是什么)

  • Shell(壳):这是一个抽象概念,指所有“命令行解释器”的统称。它是用户与操作系统内核(Kernel)之间的“翻译官”。你在黑窗口里敲的每一个字符,都由 Shell 翻译成内核能理解的指令去执行。Linux 有 Shell,Windows 也有 Shell。

  • Bash(Bourne Again SHell):这是 Linux / macOS 系统下最主流、最强大的一位“翻译官”。它是 Unix 经典 Shell(Bourne Shell)的增强版,语法灵活,支持历史命令、自动补全、强大的脚本编程(循环、数组、正则)。

  • CMD(命令提示符):这是 Windows 系统自带的老牌“翻译官”。它模拟的是 MS-DOS 时代的命令行环境,语法简单但功能较弱(不支持复杂的数学运算、数组,逻辑判断也很笨拙)。


二、它们之间的“血缘与阶层”关系(重点)

用金字塔结构来看:

1. 底层(操作系统内核):Linux 内核 / Windows 内核。

2. 中间层(翻译官接口)Shell(职业总称)

  • 这是一个标准接口。任何符合这个接口的程序,都叫 Shell。

3. 上层(具体员工/方言)

  • 站在 Linux 这边Bash、Zsh、Fish……(其中 Bash 是老大)。

  • 站在 Windows 这边CMD、PowerShell……(其中 CMD 是最老的,PowerShell 是后来的新贵)。

重要补充(Windows 的“叛变”):

严格来说,CMD 并不是 Windows 唯一的 Shell。Windows 后来开发了 PowerShell,它虽然也是 Shell,但它不是基于 DOS(如 CMD)的文本流,而是基于 .NET 的对象流。如果你把 CMD 比作“手写板”,PowerShell 就是“智能输入法”,而 Bash 则是“专业编程软件”。


三、一张表看懂本质区别(命令语法 + 底层逻辑)

对比维度 CMD (Windows 旧壳) Bash (Linux/Mac 主流壳) PowerShell (Windows 新壳)
出身 继承自 MS-DOS 继承自 Unix Bourne Shell 微软基于 .NET 重写的现代壳
路径写法 反斜杠 \C:\Users 正斜杠 //home/user 兼容 \,但也支持 /
大小写 不敏感ping 和 PING 一样) 极度敏感ping 和 Ping 是两个命令) 通常不敏感(命令不区分,但路径可区分)
变量声明 set a=10(全是字符串) a=10(默认字符串,但可声明整数/数组) $a = 10(强类型对象)
管道符 | 传输 传输纯文本(如 find "abc" 只能搜文本) 传输纯文本(文本流,配合 grep 搜文本) 传输.NET 对象(可以直接 Where-Object {$_.CPU -gt 10}
逻辑判断 极弱(只有 if errorlevel 极强(ifcaseforwhileuntil 极强(完整的编程语言)
是否有图形界面 只有黑框,不能画图 只有黑框(但可调用图形库如 dialog 只有黑框(但可调用 .NET WinForm 画界面)

四、为什么 Linux 世界里“Shell”几乎等同于“Bash”?

因为你一旦登录 Linux 服务器,默认打开的就是 Bash。所以大家在日常对话中,经常把“Shell 脚本”和“Bash 脚本”混用。

但严谨地说,Bash 只是 Shell 的一种。还有:

  • Sh(最古老的 Bourne Shell,Bash 的前身)

  • Zsh(比 Bash 更花哨,插件更丰富,macOS 默认已改用 Zsh)

  • Fish(友好交互,语法更人性化)


五、举几个例子,帮你“对号入座”

  • 比如 ping -t > log.txt:这是 CMD 指令集里的 ping.exe,但你在 PowerShell 窗口里运行它也能跑,因为 PowerShell 兼容调用外部的 .exe 程序。

  • 比如 ipconfig /flushdns:这是 CMD 的遗产,但在 Bash(Linux/Mac)里根本没这命令。对应的是 sudo systemd-resolve --flush-caches(Linux)或 sudo dscacheutil -flushcache(Mac)

  • 如果你在 Linux 的 Bash 里敲 -t:会报错,因为 Linux 的 ping 命令 -t 参数代表“TTL”,不是“持续”。


💡 一句话终极总结

  • Shell = 出租车行业(职业统称)。

  • CMD = 老式汽油出租车(Windows 自带,够用但马力小,费油)。

  • Bash = 高性能自动挡出租车(Linux 标配,马力足,能漂移)。

  • PowerShell = 新能源智能出租车(Windows 新秀,能自动驾驶,但和老司机(CMD 命令)不完全兼容)。

如果将来打算深入学习自动化运维,强烈建议大家开始熟悉 Bash(Linux)或 PowerShell(Windows),而不是停留在 CMD。因为写 CMD 批处理(.bat)调试起来极其痛苦,而 Bash 和 PowerShell 的脚本可以像写程序一样优雅。


番外:如何在 Windows 上安装 WSL(Windows Subsystem for Linux)

如果有跨平台操作的需求,我可以给大家讲讲如何在 Windows 上安装 WSL(Windows Subsystem for Linux)来体验原生的 Bash 环境。

那我们就顺着“翻译官”这个比喻继续深挖,从命令语法差异讲到跨平台实操。

1. 常用命令“翻译手册”(CMD → Bash)

如果你以后接触 Linux 服务器,下面这张对照表能帮你快速上手,不用重新学:

你的目的 CMD 写法 (Windows) Bash 写法 (Linux/macOS) 关键差异提醒
列出目录 dir ls -l-l 看详细信息) Bash 习惯用 ls,且参数前必须带 -
复制文件 copy a.txt b.txt cp a.txt b.txt Bash 叫 cp(Copy),CMD 叫 copy
移动/改名 move a.txt ./folder/ mv a.txt ./folder/ Bash 叫 mv(MoVe)。
删除文件 del a.txt rm a.txt危险! Bash 的 rm 删除后无法恢复(不进回收站)。
清屏 cls clear(或按 Ctrl+L 完全不一样。
查看网络配置 ipconfig ifconfig(旧)或 ip a(新) Linux 新系统推荐用 ip 命令。
测试连通 ping -t(持续) ping(默认就是持续) Linux 默认不停,需加 -c 4 限制次数。

2. 如何在 Windows 上体验原版 Bash(不装双系统)

既然你有探索欲,强烈建议开启 Windows 自带的 WSL(Windows Subsystem for Linux)。这相当于在 Windows 内部跑了一个轻量级 Linux 虚拟机,你可以直接在里面敲 Bash 命令,甚至运行 Linux 程序。

开启步骤(极其简单):

1. 右键“开始”菜单,选择“Windows PowerShell(管理员)”或“终端(管理员)”。

2. 输入以下命令并回车:

wsl --install

3. 重启电脑,再次打开终端,它会自动让你设置 Linux 用户名和密码。完成后,你输入 bash 就能直接进入 Linux 环境了。

这样一来,你可以在一个电脑上同时跑 CMDPowerShell 和 Bash,对比着学,理解会深好几倍。


附:关于“环境变量”的问题

大家有可能会注意到,你在 CMD 里敲 echo %PATH%,在 Bash 里敲 echo $PATH,它们都叫“环境变量”,但为什么 Windows 用 % 包着,Linux 用 $ 开头?它们是如何影响你敲的每一个命令的“寻路”过程的?接下来,我们继续拆解。

其实,这是命令行里最核心的概念之一,搞懂了它,你就能明白为什么有时候敲 python 能运行,有时候却提示“不是内部命令”。

环境变量可以理解为操作系统的一张全局便签纸,系统或程序启动时都会先瞄一眼这张便签,来决定自己该怎么运行。

1. 三巨头查看/设置变量的语法差异

这是最直观的区别,看你用哪个“翻译官”:

操作 CMD (Windows 旧壳) Bash (Linux/Mac) PowerShell (Windows 新壳)
查看单个变量 echo %PATH% echo $PATH $env:PATH
查看所有变量 set env 或 printenv Get-ChildItem Env:
临时设置(仅当前窗口) set var=123 export var=123 $env:var = "123"
彻底删除变量 set var=(置空) unset var Remove-Item Env:var

为什么 CMD 要用 % 包着? 因为 CMD 的语法老旧,它用 %变量名% 来表示“我要展开这个变量的值”。Bash 用 $ 前缀,而 PowerShell 因为面向对象,把环境变量归到了 Env: 这个驱动器下。


2. 实战之王:PATH 变量(为什么你的命令找不到?)

在所有环境变量中,PATH(或 Path 是最重要的。它存储了一堆文件夹路径(用分号 ; 隔开,Linux 用冒号 :)。

当你敲下 ping 并回车时,系统在干嘛?
它会按顺序去 PATH 变量里列出的每一个文件夹里翻找,看有没有 ping.exe(或 Linux 下的 ping)这个文件。找到第一个就执行。

故障场景重现
你刚装完 Python,但在 CMD 里敲 python 提示“不是内部或外部命令”。
原因:Python 安装程序没有把它的安装目录(比如 C:\Python39\)添加到 PATH 里,系统压根不知道去那里找。
解决方法(CMD 临时)

set PATH=C:\Python39;%PATH%

(这行命令只在当前黑窗口有效,关了就没了。永久修改要在系统设置里改,或 CMD 用 setx 命令,但 setx 有个大坑,见下文。)

3. 致命的“临时”与“永久”陷阱(必看)

这是新手最容易栽跟头的地方:

  • CMD 中的 set:只改当前窗口的内存,窗口一关,恢复原样。适合临时测试。

  • CMD 中的 setx:写进注册表,永久生效。但致命伤:它不会改变当前已经打开的这个 CMD 窗口!你必须新开一个 CMD 窗口,改动才生效。很多人在当前窗口敲 setx 后立刻敲命令,发现没用,还以为自己改错了。

  • Bash 中的 export:只改当前会话(当前终端),关掉失效。

  • Bash 中永久生效:必须把 export 语句写进配置文件,比如 ~/.bashrc 或 ~/.profile。保存后执行 source ~/.bashrc 才能让当前窗口立刻生效。

  • PowerShell 永久修改:需要使用 [Environment]::SetEnvironmentVariable("变量名", "值", "User"),功能最完善,但语法最啰嗦。


4. 查看“命令真实身份”的调试技巧

当你发现敲了命令能跑,但你想知道系统到底执行的是哪个文件夹里的程序时(比如你装了多个版本的 Java),可以用这两个命令:

  • CMDwhere ping(会显示 C:\Windows\System32\ping.exe

  • Bashwhich ping(会显示 /bin/ping

  • PowerShellGet-Command ping(因为 PowerShell 不仅能找到 .exe,还能找到内部的 Cmdlet)


5. 高级玩法:利用环境变量传参

环境变量不仅系统用,你也用。比如你在 Bash 里写:

export MY_IP="192.168.1.100"
ping $MY_IP

系统会自动把 $MY_IP 替换成 192.168.1.100 再去执行。这在编写自动化脚本时极其常用,你可以把账号密码、IP 地址都抽成变量,避免写死在代码里。


上面我们聊到了系统如何找到命令(PATH),下一步我们可以深入探讨 “进程与端口”。大家都知道我们使用 ping命令来测网络层(ICMP),但如果想测传输层(TCP/UDP)的连通性,或者看某个端口被哪个程序占用了(比如 netstat -ano),这就涉及到更底层的网络通信模型了。如果你想了解这部分的知识,可以转看下一篇:如何解决“远程端口连通性测试”与“本地端口占用进程查询”两类问题‌。‌‌


相关参考资料:

cmd 与 bash 基础命令入门 | DOS命令大全及用法?一文读懂从入门到实战的终极指南

如何使用专用工具解决“远程端口连通性测试”与“本地端口占用进程查询”两类问题‌。‌‌

网络诊断双刃剑:Tracert路由追踪实战与Windows防火墙端口配置指南

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐