251130:zsh:cd
发布: (2025年11月30日 GMT+8 11:07)
4 分钟阅读
原文: Dev.to
Source: Dev.to
目标
本次深入研究耗时 6.5 小时
本文档的目标是深入探讨以下命令:
cd /
cd -
cd
cd ..
受众
面向对 Linux 命令行操作有基本了解、希望深化目录导航命令知识的用户,提供简洁的复制‑粘贴示例。
背景
| 命令 | 描述 |
|---|---|
cd / | 切换到根目录 |
cd .. | 切换到父目录 |
cd 或 cd ~ | 切换到家目录 |
cd - | 切换到上一次所在的目录(相当于“后退”按钮) |
深入探讨
如何查看 cd 命令的源代码?
type cd
# cd is a shell builtin
cd 直接在 shell(如 bash、zsh)内部实现。
我们如何知道正在使用哪个 shell?
echo $SHELL # /bin/zsh
# or
echo $0 # -zsh
快速检查版本
zsh --version
# zsh 5.9 (arm64-apple-darwin24.0)
深入 zsh 中 cd 的 bin_cd 实现
官方仓库位于 https://github.com/zsh-users/zsh。
关键函数:
cd_get_dest()– 初始参数处理cd_do_chdir()– 执行实际的chdir()调用cd_new_pwd()– 成功切换目录后的辅助处理
受限 shell 检查
if (isset(RESTRICTED)) {
zwarnnam(nam, "restricted");
return 1;
}
zwarnnam 用于格式化警告信息。在受限模式下,cd 可能被阻止。
示例
zsh -r # 启动受限 shell
cd .. # → zsh: cd: restricted
带有追踪符号链接的 cd
chasinglinks = OPT_ISSET(ops,'P') || (isset(CHASELINKS) && !OPT_ISSET(ops,'L'));
当满足以下任一条件时,chasinglinks 为真:
- 指定了
-P选项,或 - 启用了
CHASELINKS选项,且未被-L覆盖。
测试准备
tmp_dir=$(date +%y%m%d_%H%M%S_test)
mkdir "$tmp_dir" && cd "$tmp_dir"
mkdir physical_path
ln -s physical_path symbolic_link
检查目录布局
ls -al
# total 0
# drwxr-xr-x 4 user staff 128 ... .
# drwxr-x---+ 73 user staff 2336 ... ..
# drwxr-xr-x 3 user staff 96 ... physical_path
# lrwxr-xr-x 1 user staff 13 ... symbolic_link -> physical_path
测试案例
# 默认(无 -P,也未开启 CHASE_LINKS)
cd symbolic_link
pwd # /path/to/tmp_dir/symbolic_link
# 使用 -P(物理路径)
cd ..
cd -P symbolic_link
pwd # /path/to/tmp_dir/physical_path
# 全局启用 CHASE_LINKS
cd ..
setopt CHASE_LINKS
cd symbolic_link
pwd # /path/to/tmp_dir/physical_path
# 用 -L 覆盖(逻辑路径)
cd ..
cd -L symbolic_link
pwd # /path/to/tmp_dir/symbolic_link
setopt
setopt 内建命令在 Src/options.c 中实现。
如何查看当前 shell 中已设置的选项?
/* With no arguments or options, display options. */
if (!*args) {
scanhashtable(optiontab, 1, 0, OPT_ALIAS, optiontab->printnode, !isun);
return 0;
}
setopt
# chaselinks
# combiningchars
# interactive
# …
如何查看尚未启用的选项?
unsetopt
# noaliases
# aliasfuncdef
# allexport
# …
cd 执行期间的信号处理
queue_signals(); /* block interrupt-like signals while changing directory */
阻塞信号可确保目录切换这一关键操作不被中断。
目录栈处理
zpushnode(dirstack, ztrdup(pwd));
pwd 保存了切换前的当前工作目录。可以使用以下命令查看目录栈:
dirs -v
# 0 ~/Workspaces
# 1 ~/Workspaces/oss
深入 cd_get_dest()
cd_get_dest() 根据传递给 cd 的参数确定目标目录:
- 无参数 → 返回家目录(
$HOME)。 -→ 返回目录栈中的上一次目录(OLDPWD)。- 具体路径 → 返回提供的路径(在处理
-P/-L等选项后)。
出错时返回 NULL(例如上一次目录未设置)。
文档结束。