这是《与 Shell 对话》系列的最后一篇。前六篇你学会了操作文件、搜索内容、串管道、管系统、配别名、写脚本。但无论学了多少,总会遇到问题:命令找不到、权限不够、终端突然打不开了。这篇教你自己解决问题——读懂错误信息、用终端内置的帮助系统、修复常见故障。文末附全系列所有命令的速查总表。
上一篇:从命令到脚本
| 关键词 | 一句话说明 |
|---|---|
| 错误诊断 | 看终端的报错信息来推断问题——它虽然看起来吓人,但信息量很大 |
| man | 终端内置的完整使用手册——每个命令都有,看完能懂一切选项 |
--help | 命令自带的快速帮助——比 man 短,只看常用用法 |
| which / type | 找出一个命令究竟来自哪里——是别名、内置命令、还是某个路径下的程序 |
| whatis / apropos | whatis 一句话描述命令,apropos 用关键词搜索所有手册页 |
$? | 上一条命令的退出码——0 是成功,非 0 是失败,数值告诉你失败类型 |
| PATH 修复 | 大部分 "command not found" 问题的根源——PATH 里没有包含该命令的目录 |
| 安全模式恢复 | .zshrc 改坏了导致终端打不开时的自救方法——用 /bin/zsh 绕过配置 |
| trash | 把文件移到废纸篓而不是直接删除——给自己一个后悔的机会 |
终端报错看起来冷冰冰,但它们其实非常精确。以下是你在 Mac 上最常见的五种错误,每一句都告诉你具体是什么问题。
zsh: command not found: xxx
这是最常见的错误。它只有三个可能的原因:
sl 不是 ls,gpre 不是 grep。先检查键盘python 但 Mac 上没有(需安装 Python)。用 brew install xxx 安装cat: 不存在的文件.txt: No such file or directory
你给了一个路径,但这个路径下没有这个文件。检查:
ls 路径 看看那个位置到底有什么pwd 确认你在哪调试技巧:用 ls 看路径,确认后再替换到命令中。你不是记忆力不够——你只是没先看一眼。
zsh: permission denied: ./脚本.sh
你想直接运行一个文件,但它没有执行权限。修复:
chmod +x 脚本.sh
./脚本.sh
如果是 sudo: 命令: command not found —— 注意:sudo 不会自动让"找不到的命令"变得找得到。你需要先确保命令在 PATH 中。
如果是 "Operation not permitted" 而不是 "Permission denied"——这是 macOS 的 SIP(系统完整性保护)或完全磁盘访问权限的限制。需要在「系统设置 → 隐私与安全性」中授予终端相应的权限。
grep "某个词" ~/Desktop/*
# 没有输出,没有报错,直接回到提示符
这通常不是错误——而是命令没有找到匹配。grep 没有找到包含"某个词"的行,所以它什么都没打印。试试 echo $?,如果结果是 1 而不是 0,就确认了"没有匹配"。
终端的错误信息虽然简短,但每一条都是精确的。遇到报错不要慌——先完整读一遍报错内容,而不是只看红色的部分。很多时候问题就写在字面上:比如
No such file or directory已经把问题说得不能再清楚了。
遇到不认识或不记得用法的命令时,不需要上网搜索——终端自己有完整的手册。
man ls # 看 ls 的完整手册
man grep # 看 grep 的完整手册
在 man 页面里,和 less 的操作完全一样:空格翻页,/关键词 搜索,q 退出。
大部分命令支持 --help 或 -h 选项,显示简短的用法说明,比 man 快得多:
grep --help # 快速查看 grep 的用法
chmod --help # chmod 的选项大全
注意:并非所有命令都支持 --help。macOS 的 BSD 版工具中有些只接受 man。不支持的话就用 man 命令。
whatis ls # 一句话告诉你 ls 是什么
ls(1) - list directory contents
whatis grep
grep(1) - search a file for a pattern
你知道想做什么,但不记得对应的命令叫什么——用 apropos 搜索所有手册的描述:
apropos "copy" # 搜索描述中包含 copy 的命令
cp(1) - copy files
rsync(1) - remote copy
dd(1) - convert and copy a file
apropos "compress" # 搜索压缩相关的命令
which ls # ls 这个程序在哪个目录
/bin/ls
which -a echo # 如果同一个命令有多个版本(-a 显示全部)
/bin/echo
type ls # Shell 告诉我 ls 是什么
ls is /bin/ls
type gnight # 别名或函数也会显示
gnight is an alias for pkill caffeinate 2>/dev/null; pmset sleepnow
type cd # 内置命令
cd is a shell builtin
当"命令找不到"时,which 和 type 是最直接的诊断工具——它们告诉你 Shell 到底有没有这个命令、从哪找。
这五个命令构成了一个完整的求助链条:
apropos搜索命令 →whatis确认 →man看详情 →which/type定位来源 →--help快速参考。遇到不认识的命令,走一遍这个流程,基本都能搞懂。
每条命令执行结束后都会返回一个数字给系统,叫退出码(exit code)。你可以用 $? 查看上一条命令的退出码:
ls ~/Desktop # 执行一条成功的命令
echo $?
0 # 0 = 成功
ls /不存在的目录 # 执行一条失败的命令
echo $?
1 # 非 0 = 失败
退出码的真正用途是在脚本中判断上一步是否成功:
#!/bin/zsh
grep -q "某个配置" ~/.zshrc
# $? 现在是上一条命令(grep)的退出码
if [ $? -eq 0 ]; then
echo "✅ 配置已存在"
else
echo "❌ 配置不存在,正在添加……"
echo "某个配置" >> ~/.zshrc
fi
&& 和 || 也是基于退出码工作的,你现在可以理解它们为什么这样设计了——&& 只有当左边返回 0 (成功)时才执行右边,|| 只有当左边返回非 0 (失败)时才执行右边。
遇到命令找不到,按这个顺序检查:
# 步骤 1:这个命令是否真的存在?
which 命令名 # 返回路径 → 存在。什么也不返回 → 不存在
# 步骤 2:如果存在,PATH 里有没有它的目录?
echo "$PATH" | tr ':' '\n' # 把 PATH 分行显示,看它的目录在不在里面
# 步骤 3:如果不在,把它所在的目录加到 PATH
# 在 .zshrc 里加一行:
export PATH="/某个/目录:$PATH"
source ~/.zshrc
最常见的场景:你刚用 Homebrew 安装了 wget(或任何工具),输入 wget 时提示 command not found。这说明 brew 安装成功了,但它的 bin 目录(/opt/homebrew/bin)没有在 PATH 中。检查 echo $PATH 是否包含 /opt/homebrew/bin,如果不包含,加到 .zshrc 里。
如果你改了 .zshrc 后新终端一打开就闪退或报错,别慌。macOS 提供了一个安全措施——按住 Shift 键启动终端可以跳过 .zshrc。如果不行,用替代方案:
方案一:你有备份(第五篇建议过,希望你做了):
/bin/zsh --no-rcs # 启动不带配置的纯净 zsh
cp ~/.zshrc.backup ~/.zshrc # 从备份恢复
exit # 退出纯净,重新打开终端
方案二:你没有备份(没关系,现在做还来得及):
/bin/zsh --no-rcs # 启动纯净模式
cd ~
mv .zshrc .zshrc.坏掉的 # 把坏的配置移走
# 现在新开一个终端窗口就能正常打开了
# 以后可以慢慢从 .zshrc.坏掉的 里提取有用的部分
另外,按住 Shift 键打开「终端.app」也可以跳过 .zshrc。如果「终端.app」点不开,从「访达 → 应用程序 → 实用工具」中找到它也能打开。
# Homebrew 安装在 /opt/homebrew/bin/brew(Apple Silicon Mac)
# 如果 brew 报 command not found,先试试完整路径:
/opt/homebrew/bin/brew --version
# 如果能用,只是 PATH 的问题——在 .zshrc 里加:
export PATH="/opt/homebrew/bin:/opt/homebrew/sbin:$PATH"
source ~/.zshrc
较新的 macOS 版本(Ventura 及以后)对终端访问某些目录有严格的限制。如果终端提示没有权限访问桌面、文档、下载等文件夹:
rm 删除的文件不进废纸篓。建议安装 trash 命令代替 rm:
brew install trash # 安装 trash 命令
trash 文件 # 把文件移到废纸篓(而不是直接删除)
# 然后创建一个别名:
alias rm='trash' # 以后打 rm 等于移到废纸篓
# 注意:这只在交互式终端有效,脚本里的 rm 仍然是原始的 rm
如果你已经用 rm 删了重要文件:立即停止使用电脑,用数据恢复工具(如 TestDisk、Disk Drill)尝试恢复。但成功率取决于你是否继续向硬盘写入新数据。
大多数"终端问题"可以归结为三类:路径不对(检查 pwd)、权限不够(检查 chmod/sudo)、程序找不到(检查 PATH)。先把这三个地方查一遍,能解决 90% 的问题。剩下的 10% 用
man和 Google 解决。
以下按功能分类汇总了本系列涉及的所有命令,方便日后查阅。
| 命令 | 作用 | 来自 |
|---|---|---|
pwd | 显示当前目录 | 第一篇 |
ls | 列出目录内容 | 第一篇 |
cd | 切换目录 | 第一篇 |
find | 按条件搜索文件 | 第二篇 |
mdfind | Spotlight 搜索 | 第二篇 |
open | 用默认程序打开文件/目录/URL | 第一篇 |
basename | 从路径中提取文件名 | 第六篇 |
dirname | 从路径中提取目录部分 | 第六篇 |
| 命令 | 作用 | 来自 |
|---|---|---|
cp | 复制文件或目录(-r 递归) | 第一篇 |
mv | 移动或重命名 | 第一篇 |
rm | 删除(不进废纸篓) | 第一篇 |
mkdir | 创建目录(-p 创建中间层级) | 第一篇 |
touch | 创建空文件或更新修改时间 | 第一篇 |
file | 检测文件真实类型 | 第二篇 |
du | 查看磁盘用量(-sh 汇总人类可读) | 第二篇 |
df | 查看磁盘剩余空间(-h) | 第二篇 |
wc | 统计行数/词数/字节数(-l) | 第二篇 |
trash | 移到废纸篓(需 brew install) | 第七篇 |
| 命令 | 作用 | 来自 |
|---|---|---|
cat | 输出文件内容到屏幕(短文件) | 第二篇 |
less | 分页查看(长文件) | 第二篇 |
head | 看文件开头几行(-n) | 第二篇 |
tail | 看文件末尾几行 / 实时追踪(-f) | 第二篇 |
grep | 在内容中搜索(-rin / -v / -c / -l / -L) | 第二篇 |
sort | 排序(-n / -h / -r / -k) | 第三篇 |
uniq | 去重并统计(-c) | 第三篇 |
| 符号/命令 | 作用 | 来自 |
|---|---|---|
> | stdout → 文件(覆盖) | 第三篇 |
>> | stdout → 文件(追加) | 第三篇 |
2> | stderr → 文件 | 第三篇 |
&> | stdout + stderr → 同一文件 | 第三篇 |
2>&1 | stderr → stdout 所在位置 | 第三篇 |
| | 管道:前命令的 stdout → 后命令的 stdin | 第三篇 |
tee | 同时输出到屏幕和文件 | 第三篇 |
xargs | 将 stdin 转为命令参数 | 第三篇 |
| 命令 | 作用 | 来自 |
|---|---|---|
ps | 查看进程快照(aux) | 第四篇 |
top | 实时进程监控(按 q 退出) | 第四篇 |
kill | 按 PID 终止进程(-9 强制) | 第四篇 |
pkill | 按名字终止进程 | 第四篇 |
jobs / fg / bg | 前后台作业管理 | 第四篇 |
nohup | 关闭终端后继续运行 | 第四篇 |
caffeinate | 阻止自动睡眠(macOS 特有) | 第四篇 |
chmod | 修改文件权限(+x / 755 / 644) | 第四篇 |
sudo | 超级用户执行 | 第四篇 |
whoami / id | 查看当前用户身份 | 第四篇 |
sw_vers | 查看 macOS 版本 | 第四篇 |
uname | 查看系统内核信息(-a) | 第四篇 |
uptime | 查看运行时长 | 第四篇 |
date / cal | 查看日期和日历 | 第四篇 |
sysctl | 查看硬件信息(hw.memsize / hw.ncpu) | 第四篇 |
pmset | 电源管理(sleepnow) | 外传 |
| 命令 | 作用 | 来自 |
|---|---|---|
pbcopy / pbpaste | 终端与系统剪贴板交互 | 第四篇 |
say | 文字转语音 | 第四篇 |
defaults | 读写系统隐藏设置 | 第四篇 |
open | 从终端打开任何东西 | 第一篇 |
mdfind | Spotlight 搜索命令版 | 第二篇 |
| 命令/操作 | 作用 | 来自 |
|---|---|---|
alias | 查看/创建别名 | 第五篇 |
unalias | 删除别名 | 第五篇 |
export | 设置环境变量(传给予进程) | 第五篇 |
source | 重新加载配置文件 | 第五篇 |
env | 查看所有环境变量 | 第五篇 |
history | 查看命令历史 | 第五篇 |
echo $变量 | 查看单个变量值 | 第三篇 |
| 语法 | 作用 | 来自 |
|---|---|---|
#!/bin/zsh | Shebang——指定解释器 | 第六篇 |
$(命令) | 命令替换 | 第六篇 |
$1 $2 $@ $# | 脚本参数 | 第六篇 |
${1:-默认值} | 参数默认值 | 第六篇 |
[ 条件 ] | 条件判断 | 第六篇 |
if/then/elif/else/fi | 分支结构 | 第六篇 |
for/do/done | 遍历循环 | 第六篇 |
while/do/done | 条件循环 | 第六篇 |
set -x / set +x | 调试模式开关 | 第六篇 |
exit n | 以指定退出码终结 | 第六篇 |
$(( )) | 算术运算 | 第六篇 |
$? | 上条命令的退出码 | 第六篇 |
| 快捷键 | 作用 | 来自 |
|---|---|---|
Tab | 自动补全命令/路径 | 第一篇 |
↑ ↓ | 翻查命令历史 | 第一篇 |
Ctrl + C | 终止当前命令 | 第一篇 |
Ctrl + D | 退出 Shell / EOF | 第一篇 |
Ctrl + A / E | 光标到行首/行尾 | 第一篇 |
Ctrl + U / W | 删到行首 / 删一个词 | 第一篇 |
Ctrl + L | 清屏 | 第一篇 |
Ctrl + R | 交互式搜索命令历史 | 第五篇 |
Ctrl + Z | 暂停当前命令(放到后台) | 第四篇 |
!! | 重复上一条命令 | 第五篇 |
!$ | 上条命令的最后一个参数 | 第五篇 |
这个系列覆盖了终端使用的核心能力。如果你还想深入,以下方向值得探索:
| 方向 | 为何值得学 | 起步建议 |
|---|---|---|
| 正则表达式 | grep、sed、awk、脚本中的文本处理核心技能 | 先学好 grep 的 -E 模式,然后学 sed 替换 |
| sed 和 awk | 文本处理的终极利器——一个按行处理,一个按列处理 | 先学 sed 替换(s/旧/新/),再学 awk 列提取 |
| git 版本控制 | 管理代码和文档的版本历史,终端的杀手级应用 | 学完基本的 commit/push/pull 就够日常用 |
| Homebrew 打包 | 写自己的 brew formula,让任何人都能安装你的脚本 | 现在就可以用 brew 安装几乎所有开源工具 |
| tmux / screen | 终端复用器——一个窗口开多个会话,SSH 不断线 | 先装 tmux,学基本的新建/切换/分离 |
| 网络工具 | curl、ping、ssh、scp——终端里的网络操作 | 从 curl 开始,它可以下载文件和调用 API |
系列回顾
七篇笔记,从打开终端窗口到写自己的脚本。如果按顺序读下来,你已经掌握了 macOS 终端最核心的能力:操作文件(第一篇)、搜索内容(第二篇)、管道组合(第三篇)、管理系统(第四篇)、配置环境(第五篇)、编写脚本(第六篇)、解决问题(第七篇)。
但这只是一个开始。终端不是"学会"的——它是"用会"的。真正熟练的标志不是你记住了多少命令,而是遇到一个重复劳动时,你下意识地想:"这能不能用一个命令搞定?"
终端最大的魅力在于:你的效率提升没有上限。 每次学到一个新技巧,过去的很多操作就又多了一种更快的做法。这七篇笔记放在这里,任何时候想回查都可以翻回来。祝你用得愉快。