这是《与 Shell 对话》系列的第五篇。前四篇你在学"Shell 能做什么"——操作文件、搜索内容、串管道、管理系统。这一篇反过来:让 Shell 记住你的习惯、缩短你的操作路径、把重复劳动变成一次按键。学完这篇,你的终端环境将是独一无二的——完全按照你的节奏工作的工具。
| 关键词 | 一句话说明 |
|---|---|
| 别名(alias) | 给一个长命令起一个短名字——alias ll='ls -la',以后打 ll 就行 |
| Shell 函数 | 比别名更灵活——可以接收参数、包含多行逻辑,像一段小程序 |
| 环境变量 | Shell 中的全局配置变量——PATH 决定去哪找程序,HOME 知道你家在哪 |
| export | 把变量传递给子进程——不加 export 的话,变量只属于当前 Shell |
| PATH | 最重要的环境变量——告诉 Shell "去这些目录找可执行程序" |
| .zshrc | zsh 的配置文件——每次打开终端时自动加载,别名和环境变量写在这里才持久 |
| source | 重新加载配置文件——改完 .zshrc 后不用关终端,source ~/.zshrc 即刻生效 |
| Ctrl+R | 搜索命令历史——输入几个字符就能找回以前敲过的任何命令 |
!! | 快捷操作:重复上一条命令。忘了加 sudo?sudo !! |
| dotfile | 以 . 开头的配置文件——默认隐藏,ls -a 才能看见 |
在前面的文章中,你一直在用 ls -la 这个组合。如果每次都要打完整的 ls -la,很快你会觉得烦。别名的意义就在于此。
alias # 列出当前所有别名
ll='ls -lh'
la='ls -la'
...
你的 Mac 上可能已经有几个预设别名了(macOS 默认会给 ls 加上颜色等)。试试看——你会发现终端已经替你省了些事。
alias ll='ls -la' # 以后打 ll 就等于 ls -la
alias gnight='pkill caffeinate 2>/dev/null; pmset sleepnow' # 一键睡眠(完整版)
# 安全别名——给危险命令加一道确认
alias rm='rm -i' # 每次 rm 都先问你确认
alias cp='cp -i' # 覆盖文件前询问
alias mv='mv -i' # 移动覆盖前询问
试试在终端里输入这些别名,然后测试它们的效果:
alias ll='ls -la' # 创建
ll ~/Desktop # 测试——效果等同 ls -la ~/Desktop
unalias ll # 删除别名
ll ~/Desktop # 现在报错了——command not found
不过这里有一个问题:在当前终端创建的别名,新开一个窗口就没了。别名的"持久化"需要写进配置文件(.zshrc), 这篇后面会讲。
别名看似简单,但它体现了一种思维方式:留意重复劳动。 如果你发现自己每天要打好几遍同样的长命令——那就是一个创建别名的信号。不要忍着,花 5 秒钟设个别名。
别名只能做一件事:把一串文字替换成另一串文字。如果你想在命令的中途插入参数——比如 cd 某个新建的文件夹 这种场景——别名就做不到了。这时候需要函数。
函数和别名的区别:别名是文字替换,函数是真正的程序逻辑。 函数可以接收参数、包含多行逻辑、使用变量。
# 定义一个函数——"创建目录并走进去"
mcd() {
mkdir -p "$1"
cd "$1"
}
# 使用
mcd ~/Desktop/新文件夹 # 创建并进入
pwd
/Users/aodesai/Desktop/新文件夹
这里的 $1 是函数的第一个参数(你把文件夹名传给它)。$2 是第二个,依此类推。
把这些加入你的 .zshrc,终端会变得顺手很多:
# 回到上一级并查看目录内容
up() {
cd ..
ls
}
# 快速打开一个文件,如果不存在则创建
note() {
touch "$1"
open "$1"
}
# 按文件名搜索历史命令(比 Ctrl+R 更直接)
h() {
history | grep "$1" | head -20
}
# 用 VS Code 打开文件
# 不传参数时打开当前目录
# 函数名用 vsc 而非 code——避免和 VS Code 自带的 code 命令行工具冲突
vsc() {
if [ -z "$1" ]; then
open -a "Visual Studio Code" .
else
open -a "Visual Studio Code" "$1"
fi
}
函数 vs 别名的选择原则:如果只是给命令加固定选项 → 别名。如果需要处理参数、条件判断 → 函数。 你的
gnight别名(杀掉 caffeinate 然后睡眠)用别名就够了,因为它只是把两件事按顺序做。但上面的vsc函数——"没有参数时打开当前目录,有参数时打开指定文件"——就需要函数。
每次你打开终端,Shell 会记住一些关于你的信息——你的用户名、你的家目录、去哪找程序。这些信息存储在一组"变量"里,你可以查看和修改它们。
echo "$HOME" # 你的家目录
/Users/aodesai
echo "$USER" # 你的用户名
aodesai
echo "$SHELL" # 你用的 Shell
/bin/zsh
echo "$PATH" # 最重要的变量——去哪找程序
/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:...
变量名前加 $ 表示"取这个变量的值"。PATH 和 HOME 是系统设置的,$ 是约定俗成的标记。
用 env 查看所有环境变量(输出很长,建议 env | less 或 env | grep 关键词):
env | grep "PATH" # 只看 PATH 相关的变量
env | wc -l # 你的 Shell 里有多少个环境变量
PATH 决定了当你输入一个命令时,Shell 去哪找对应的程序。它是一组目录路径,用 : 分隔:
/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin
当你输入 ls,Shell 按顺序查找这些目录:先找 /opt/homebrew/bin/ls,没有就找 /usr/local/bin/ls,再找 /usr/bin/ls……直到找到为止。第一个找到的被执行。
为什么这个顺序重要?因为 Homebrew(你的 brew 命令)安装的程序在 /opt/homebrew/bin 里。如果 /usr/bin 排在前面,系统自带的旧版本会覆盖 Homebrew 安装的新版本。
# 不加 export:变量只在当前 Shell 有效
MY_VAR="你好"
echo "$MY_VAR" # 输出"你好"
bash -c 'echo "$MY_VAR"' # 新开的子 Shell 中为空——没传过去
# 加 export:变量会传给子 Shell
export MY_VAR="你好"
bash -c 'echo "$MY_VAR"' # 输出"你好"——传过去了
日常使用中,几乎所有的变量都需要 export——除非你明确知道它只在当前 Shell 内使用。所以习惯直接写 export 变量名=值。
当你安装了一个新的命令行工具,有时需要把它的目录加到 PATH 中。在 .zshrc 里加一行:
export PATH="$HOME/我的脚本:$PATH"
这行代码的意思是:让 Shell 优先在 ~/我的脚本 目录里找程序,找不到时再走原来的 PATH。$PATH 引用了原来的值并加在后面——这是一种"追加但不覆盖"的模式。
如果你发现终端提示
command not found但你明明装了这个程序——先查 PATH。 大多数"安装后找不到命令"的问题,不是因为没装好,而是因为安装程序没有自动把它的路径加到 PATH 里。你自己加上就行。
以上所有配置——别名、函数、环境变量——如果你只在终端里输入,它们只对当前会话有效。关掉终端就没了。.zshrc 就是让它们"永久有效"的地方。
.zshrc 是 zsh 的配置文件,放在你的家目录下(~/.zshrc)。每当你打开一个新的终端窗口,zsh 会自动读取这个文件里的内容,执行里面的命令。
文件名以 . 开头,意味着它在访达里默认不可见——但你用 ls -a 或 cat ~/.zshrc 就能看到它。
cat ~/.zshrc # 看看你当前配置了什么
你之前添加的 alias gnight=... 就在里面。
不要用 TextEdit(文本编辑)打开它——它会自动换行和加格式。用终端编辑器:
open -a "Visual Studio Code" ~/.zshrc # 用 VS Code 打开
nano ~/.zshrc # 或者用终端内置编辑器 nano
在 .zshrc 里,建议按这个顺序组织内容:
# 1. 环境变量(放最前面)
export PATH="$HOME/bin:$PATH"
export EDITOR="nano" # 默认编辑器(git commit 等会用它)
# 2. 别名
alias ll='ls -la'
alias gnight='pkill caffeinate 2>/dev/null; pmset sleepnow'
alias rm='rm -i'
# 3. 函数
mcd() {
mkdir -p "$1"
cd "$1"
}
h() {
history | grep "$1"
}
# 用 VS Code 打开文件。函数名用 vsc 而非 code,
# 避免与 VS Code 自带的 code 命令行工具冲突
vsc() {
if [ -z "$1" ]; then
open -a "Visual Studio Code" .
else
open -a "Visual Studio Code" "$1"
fi
}
改完 .zshrc 后,新开的终端窗口会自动加载新配置。如果想让当前窗口也生效:
source ~/.zshrc # 重新加载配置文件
source 命令在当前 Shell 中逐行执行指定文件的内容——相当于"假装我又读了一遍配置文件"。
改 .zshrc 之前,建议先备份:
cp ~/.zshrc ~/.zshrc.backup # 改之前备份
# ... 编辑修改 ...
# 如果改出问题,恢复:
cp ~/.zshrc.backup ~/.zshrc
最常见的 .zshrc 问题是语法错误——比如引号没成对、括号没闭合。如果改完后所有新终端都打不开了……别慌,用 /bin/zsh 启动一个纯净的 Shell,然后用 cp 备份回来 恢复。
.zshrc 是你的"终端记忆体"。每一次你配置进去的东西,都在减小你未来重复劳动的量。花 10 分钟配置好别名和常用变量,未来一年省下的是几个小时甚至几十个小时的反复输入。
你敲过的每一条命令,Shell 都记录了下来。用好历史记录,你基本不需要重复输入任何命令。
history # 列出最近的所有命令
history | tail -20 # 只看最近 20 条
history | grep "ssh" # 搜索历史中带 ssh 的命令
用 history 配合 grep 是找回"我上周用过一条长命令但忘了具体是什么"的最佳方式。
这是你可能用得最多的快捷键之一:
# 按 Ctrl+R 后输入关键词,Shell 会实时搜索你的历史
# 假设你敲过:find ~/Desktop -name "*.md" -type f | wc -l
# 按 Ctrl+R
# 反向搜索命令历史:
# 输入 "find"(或者 "md"、"Desktop" 等关键词)
# Shell 实时展示匹配的最近一条命令
# 继续按 Ctrl+R 看更早的匹配
# 找到后按回车执行,或按 → 编辑
这和 history | grep 效果相似,但 Ctrl+R 是交互式的——输入字母实时匹配,不需要额外敲管道和 grep。
| 操作 | 效果 | 示例 |
|---|---|---|
!! | 重复上一条命令 | sudo !! = 用 sudo 再执行一次 |
!$ | 上一条命令的最后一个参数 | 刚刚 cat 很长的文件名.txt → 现在 rm !$ |
!n | 执行历史中第 n 条命令 | 看到 history 里 1234 是你想要的 → !1234 |
!字符串 | 执行最近一条以该字符串开头的命令 | !cat → 执行最近一次 cat 命令 |
↑ ↓ | 逐条翻阅历史 | 按 ↑ 回到上一条,继续按 ↑ 回到更早 |
最常用的是 sudo !!——你敲了一条命令,提示"权限不够",这时输入 sudo !! 就行了。
历史记录存储在 ~/.zsh_history 文件中。关掉终端再打开,历史不会丢失。history 命令能看到所有会话的记录。
wc -l ~/.zsh_history # 你的历史记录里有多少条命令
默认的 zsh 会保存最近 2000 条命令。如果你觉得不够,可以在 .zshrc 里修改:
export HISTSIZE=5000 # 内存中保留的命令数
export SAVEHIST=5000 # 文件中保存的命令数
关于历史记录的一个小建议:不要怕敲错命令。 敲错了删掉重来——这条"错误命令"也被记录下来了。没关系,Ctrl+R 只会匹配关键词,你不会因为打错过就被污染。真正的好习惯是:遇到一条复杂的命令,只要它成功运行了,就值得在评论区写一句注释——以备以后查阅历史记录时能看懂它。
这个练习和前几篇不同——它不是一次性的,而是你终端配置的起点。做完后你的 Shell 会"记住"你。
看看当前 .zshrc 里有什么,看看你的 PATH 里有哪些目录。
cat ~/.zshrc
echo "$PATH" | tr ':' '\n' # 把 PATH 按 : 换行显示,一目了然
# tr 是"字符替换"命令,这里把 : 替换成换行符 \n
备份当前 .zshrc,然后添加一批你用得到的别名。
# 先备份
cp ~/.zshrc ~/.zshrc.backup.$(date "+%Y%m%d")
# 用 VS Code 打开编辑
open -a "Visual Studio Code" ~/.zshrc
# 在文件末尾添加下面几行:
# alias ll='ls -la'
# alias ..='cd ..'
# alias gnight='pkill caffeinate 2>/dev/null; pmset sleepnow'
# alias rm='rm -i'
# 保存,然后加载
source ~/.zshrc 在 .zshrc 里添加 mcd 函数——创建目录并走进去。
# 在 .zshrc 末尾加:
# mcd() {
# mkdir -p "$1"
# cd "$1"
# }
source ~/.zshrc
mcd ~/Desktop/test-mcd # 测试
pwd # 应该显示在 test-mcd 里
rmdir ~/Desktop/test-mcd # 清理
按 Ctrl+R,输入你之前用过的一个命令的一部分(比如 grep 或 sleep),找到一条历史命令并执行。
# 按 Ctrl+R
# 输入: grep
# 看到匹配的命令出现后,按回车执行
# 或者按 → 编辑后再执行
随便敲一条命令,然后用 !! 或 sudo !! 重试它。
echo "测试" # 随便执行一条命令
!! # 再次执行上一条
sudo !! # 如果需要,用 sudo 重试
到现在为止,你已经从"被动的命令使用者"变成了"主动的环境构建者"。配置 .zshrc 是你终端生涯的一个里程碑——它意味着你不再接受默认设置,而是让工具适应你。后续每当你发现一个重复动作,都可以回到 .zshrc 添一笔。它永远跟着你,越用越顺手。
| 名称 | 作用 | 最常用法 |
|---|---|---|
alias | 创建/查看别名 | alias 名字='命令' alias(查看全部) |
unalias | 删除别名 | unalias 名字 |
export | 设置环境变量(传给予进程) | export 变量名=值 |
env | 查看所有环境变量 | env \| grep 关键词 |
echo $变量 | 查看单个变量的值 | echo "$PATH" |
source | 重新加载配置文件 | source ~/.zshrc |
history | 查看命令历史 | history \| grep 关键词 |
Ctrl+R | 交互式搜索历史 | 按 Ctrl+R → 输入关键词 |
!! | 重复上一条命令 | sudo !! |
!$ | 上一条命令的最后一个参数 | cat 文件 !$ |
alias -g 可以在命令的任何位置展开,不限于开头$变量 vs "$变量" vs '$变量' 的差异:引号决定变量是否展开