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 ..切换到父目录
cdcd ~切换到家目录
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)

深入 zshcdbin_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(例如上一次目录未设置)。


文档结束。

Back to Blog

相关文章

阅读更多 »

第1276天:职业攀升

星期六 在前往车站之前,我在当前的副项目上写了一些代码。取得了相当不错的进展,然后该出发了。Made i...

无状态 AI 应用背后的架构

项目一开始就做了一个看似冒险的决定:不使用后端数据库。当时并不需要持久化用户数据——获取用户的响应就是……

失去信心

请提供您希望翻译的文章摘录或摘要文本,我才能为您进行简体中文翻译。