← 完全使用手册

与 Shell 对话 · 让你的 Shell 认识你

棱镜2026.6.3  ·  日志

这是《与 Shell 对话》系列的第五篇。前四篇你在学"Shell 能做什么"——操作文件、搜索内容、串管道、管理系统。这一篇反过来:让 Shell 记住你的习惯、缩短你的操作路径、把重复劳动变成一次按键。学完这篇,你的终端环境将是独一无二的——完全按照你的节奏工作的工具。

上一篇:面向系统的操作  ·  下一篇:从命令到脚本

🔑 关键词索引

关键词一句话说明
别名(alias)给一个长命令起一个短名字——alias ll='ls -la',以后打 ll 就行
Shell 函数比别名更灵活——可以接收参数、包含多行逻辑,像一段小程序
环境变量Shell 中的全局配置变量——PATH 决定去哪找程序,HOME 知道你家在哪
export把变量传递给子进程——不加 export 的话,变量只属于当前 Shell
PATH最重要的环境变量——告诉 Shell "去这些目录找可执行程序"
.zshrczsh 的配置文件——每次打开终端时自动加载,别名和环境变量写在这里才持久
source重新加载配置文件——改完 .zshrc 后不用关终端,source ~/.zshrc 即刻生效
Ctrl+R搜索命令历史——输入几个字符就能找回以前敲过的任何命令
!!快捷操作:重复上一条命令。忘了加 sudo?sudo !!
dotfile. 开头的配置文件——默认隐藏,ls -a 才能看见

一、别名——给命令起更短的名字

在前面的文章中,你一直在用 ls -la 这个组合。如果每次都要打完整的 ls -la,很快你会觉得烦。别名的意义就在于此。

1.1 查看已有的别名

alias                         # 列出当前所有别名
ll='ls -lh'
la='ls -la'
...

你的 Mac 上可能已经有几个预设别名了(macOS 默认会给 ls 加上颜色等)。试试看——你会发现终端已经替你省了些事。

1.2 创建自己的别名

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 秒钟设个别名。

1.3 别名的局限

别名只能做一件事:把一串文字替换成另一串文字。如果你想在命令的中途插入参数——比如 cd 某个新建的文件夹 这种场景——别名就做不到了。这时候需要函数。

二、Shell 函数——当别名不够用时

函数和别名的区别:别名是文字替换,函数是真正的程序逻辑。 函数可以接收参数、包含多行逻辑、使用变量。

2.1 最简单的函数

# 定义一个函数——"创建目录并走进去"
mcd() {
    mkdir -p "$1"
    cd "$1"
}

# 使用
mcd ~/Desktop/新文件夹         # 创建并进入
pwd
/Users/aodesai/Desktop/新文件夹

这里的 $1 是函数的第一个参数(你把文件夹名传给它)。$2 是第二个,依此类推。

2.2 几个实用的 Shell 函数

把这些加入你的 .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 知道的事

每次你打开终端,Shell 会记住一些关于你的信息——你的用户名、你的家目录、去哪找程序。这些信息存储在一组"变量"里,你可以查看和修改它们。

3.1 查看环境变量

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:...

变量名前加 $ 表示"取这个变量的值"。PATHHOME 是系统设置的,$ 是约定俗成的标记。

env 查看所有环境变量(输出很长,建议 env | lessenv | grep 关键词):

env | grep "PATH"             # 只看 PATH 相关的变量
env | wc -l                   # 你的 Shell 里有多少个环境变量

3.2 PATH——最重要的环境变量

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 安装的新版本。

3.3 设置自己的变量

# 不加 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 变量名=值

3.4 修改 PATH

当你安装了一个新的命令行工具,有时需要把它的目录加到 PATH 中。在 .zshrc 里加一行:

export PATH="$HOME/我的脚本:$PATH"

这行代码的意思是:让 Shell 优先在 ~/我的脚本 目录里找程序,找不到时再走原来的 PATH。$PATH 引用了原来的值并加在后面——这是一种"追加但不覆盖"的模式。

如果你发现终端提示 command not found 但你明明装了这个程序——先查 PATH。 大多数"安装后找不到命令"的问题,不是因为没装好,而是因为安装程序没有自动把它的路径加到 PATH 里。你自己加上就行。

四、.zshrc——你的终端配置文件

以上所有配置——别名、函数、环境变量——如果你只在终端里输入,它们只对当前会话有效。关掉终端就没了。.zshrc 就是让它们"永久有效"的地方。

4.1 什么是 .zshrc

.zshrc 是 zsh 的配置文件,放在你的家目录下(~/.zshrc)。每当你打开一个新的终端窗口,zsh 会自动读取这个文件里的内容,执行里面的命令。

文件名以 . 开头,意味着它在访达里默认不可见——但你用 ls -acat ~/.zshrc 就能看到它。

cat ~/.zshrc                  # 看看你当前配置了什么

你之前添加的 alias gnight=... 就在里面。

4.2 编辑 .zshrc 的最佳实践

不要用 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
}

4.3 让修改生效

改完 .zshrc 后,新开的终端窗口会自动加载新配置。如果想让当前窗口也生效:

source ~/.zshrc               # 重新加载配置文件

source 命令在当前 Shell 中逐行执行指定文件的内容——相当于"假装我又读了一遍配置文件"。

4.4 ⚠️ 一个安全习惯

改 .zshrc 之前,建议先备份:

cp ~/.zshrc ~/.zshrc.backup   # 改之前备份
# ... 编辑修改 ...
# 如果改出问题,恢复:
cp ~/.zshrc.backup ~/.zshrc

最常见的 .zshrc 问题是语法错误——比如引号没成对、括号没闭合。如果改完后所有新终端都打不开了……别慌,用 /bin/zsh 启动一个纯净的 Shell,然后用 cp 备份回来 恢复。

.zshrc 是你的"终端记忆体"。每一次你配置进去的东西,都在减小你未来重复劳动的量。花 10 分钟配置好别名和常用变量,未来一年省下的是几个小时甚至几十个小时的反复输入。

五、历史记录——你的记忆外挂

你敲过的每一条命令,Shell 都记录了下来。用好历史记录,你基本不需要重复输入任何命令。

5.1 查看历史

history                       # 列出最近的所有命令
history | tail -20            # 只看最近 20 条
history | grep "ssh"          # 搜索历史中带 ssh 的命令

history 配合 grep 是找回"我上周用过一条长命令但忘了具体是什么"的最佳方式。

5.2 最重要的快捷键——Ctrl+R

这是你可能用得最多的快捷键之一:

# 按 Ctrl+R 后输入关键词,Shell 会实时搜索你的历史
# 假设你敲过:find ~/Desktop -name "*.md" -type f | wc -l

# 按 Ctrl+R
# 反向搜索命令历史:
# 输入 "find"(或者 "md"、"Desktop" 等关键词)
# Shell 实时展示匹配的最近一条命令
# 继续按 Ctrl+R 看更早的匹配
# 找到后按回车执行,或按 → 编辑

这和 history | grep 效果相似,但 Ctrl+R 是交互式的——输入字母实时匹配,不需要额外敲管道和 grep。

5.3 快捷操作

操作效果示例
!!重复上一条命令sudo !! = 用 sudo 再执行一次
!$上一条命令的最后一个参数刚刚 cat 很长的文件名.txt → 现在 rm !$
!n执行历史中第 n 条命令看到 history 里 1234 是你想要的 → !1234
!字符串执行最近一条以该字符串开头的命令!cat → 执行最近一次 cat 命令
↑ ↓逐条翻阅历史按 ↑ 回到上一条,继续按 ↑ 回到更早

最常用的是 sudo !!——你敲了一条命令,提示"权限不够",这时输入 sudo !! 就行了。

5.4 历史记录的持久性

历史记录存储在 ~/.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

Ctrl+R,输入你之前用过的一个命令的一部分(比如 grepsleep),找到一条历史命令并执行。

👆 查看参考命令
# 按 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 文件 !$

待延伸线索


← 上一篇:面向系统的操作 下一篇:从命令到脚本 →