pwd 命令详解与参数实测(Ubuntu 22.04)

pwd 命令逐参数实测详解:内建 pwd 与 /bin/pwd 双实现对照、-L 逻辑路径与 -P 物理路径软链差异、PWD 环境变量、已删除目录等边界行为与脚本取真实路径实战,全部命令与回显在 Ubuntu 22.04 实测通过。

Linux命令Linux系统UbuntuUbuntu 22.04命令行文件管理2026/10/15

pwd 命令详解与参数实测(Ubuntu 22.04)

目标:全面掌握 pwd 的两个实现与两个参数——shell 内建 pwd 与 /bin/pwd(GNU coreutils)的差异、-L 逻辑路径与 -P 物理路径在软链目录下的实测对照、PWD 环境变量、已删除目录等边界行为,全部命令与回显已在 Ubuntu 22.04(内建 pwd 属 GNU bash 5.1.16,/bin/pwd 属 GNU coreutils 8.32)实测通过。

一、环境信息

本节记录实测环境与演示数据,便于读者对照复现。pwd 看似最简单的命令,实际存在「shell 内建」与「独立程序」两个实现,二者的默认语义并不相同,环境信息里一并注明版本来源。

  • 操作系统:Ubuntu 22.04.5 LTS(x86_64)
  • Shell:GNU bash 5.1.16(内建 pwd 即来自 bash)
  • /bin/pwd 版本:GNU coreutils 8.32(软件包 coreutils 8.32-4.1ubuntu1.4,见 3.5 实测)
  • 演示目录:/root/demo/pwd/
  • 测试数据:真实目录 real/(内含 note.txt)与指向它的软链 link,用于触发 -L 与 -P 的路径差异

二、命令概览

2.1 语法与测试数据准备

pwd 的职责是打印当前工作目录的完整路径。它有两个"身份",语法略有差别:

  • shell 内建 pwd:pwd [-LP],默认行为等价于 -L(信任 PWD 环境变量);
  • 独立程序 /bin/pwd:/bin/pwd [-L | -P],不跟参数时默认 -P(解析全部软链,见帮助原文末行 "If no option is specified, -P is assumed.")。

-L(logical)打印逻辑路径,即 PWD 环境变量里记录的、包含软链成分的路径;-P(physical)打印物理路径,即把所有软链解析到真实目录后的路径。两者在软链场景下会给出不同结果,这是本文实测的主线。

先准备一套「真实目录 + 指向它的软链」演示数据,后续所有参数实测都基于这套数据:

mkdir -p /root/demo/pwd/real
echo 'hello pwd' > /root/demo/pwd/real/note.txt
ln -s /root/demo/pwd/real /root/demo/pwd/link

验证数据就绪——link 的类型位是 l,指向 /root/demo/pwd/real:

$ ls -l /root/demo/pwd
total 4
lrwxrwxrwx 1 root root   19 Oct 15 06:10 link -> /root/demo/pwd/real
drwxr-xr-x 2 root root 4096 Oct 15 06:10 real

2.2 --help 全量回显

内建 pwd 与 /bin/pwd 的帮助是两份独立文本,本节全部收录。先看内建 pwd(通过 pwd --help 触发):

pwd: pwd [-LP]
    Print the name of the current working directory.
    
    Options:
      -L	print the value of $PWD if it names the current working
    		directory
      -P	print the physical directory, without any symbolic links
    
    By default, `pwd' behaves as if `-L' were specified.
    
    Exit Status:
    Returns 0 unless an invalid option is given or the current directory
    cannot be read.

再看 /bin/pwd 的帮助(coreutils 实现):

Usage: /bin/pwd [OPTION]...
Print the full filename of the current working directory.

  -L, --logical   use PWD from environment, even if it contains symlinks
  -P, --physical  avoid all symlinks
      --help     display this help and exit
      --version  output version information and exit

If no option is specified, -P is assumed.

NOTE: your shell may have its own version of pwd, which usually supersedes
the version described here.  Please refer to your shell's documentation
for details about the options it supports.

GNU coreutils online help: <https://www.gnu.org/software/coreutils/>
Report any translation bugs to <https://translationproject.org/team/>
Full documentation <https://www.gnu.org/software/coreutils/pwd>
or available locally via: info '(coreutils) pwd invocation'

💡 说明:两份帮助各只有 -L、-P 两个功能参数,但默认语义相反——内建默认 -L,/bin/pwd 默认 -P,且 /bin/pwd 的帮助末尾明确提示"你的 shell 可能有自己的 pwd 版本"。记住这条,就能解释 3.4 中同一目录两种输出的现象。

2.3 版本确认

确认两个实现各自的身份与版本:

$ type pwd
pwd is a shell builtin
$ /bin/pwd --version | head -1
pwd (GNU coreutils) 8.32

type pwd 表明日常敲的 pwd 走的是 bash 内建;/bin/pwd --version 确认独立程序来自 coreutils 8.32。

三、参数逐项实测

3.1 无参数:打印当前工作目录(默认 -L 语义)

不带任何参数,内建 pwd 打印当前目录。先进入真实目录 real/:

$ cd /root/demo/pwd/real
$ pwd
/root/demo/pwd/real
$ echo PWD=$PWD
PWD=/root/demo/pwd/real

在无软链的正常目录里,pwd 输出与 PWD 环境变量的值一致——PWD 由 shell 在每次 cd 成功后自动维护,内建 pwd 默认(-L 语义)就是把这个变量打印出来。

💡 提示:脚本报错排查时,echo PWD=$PWD 与 pwd 联用可以确认"shell 认为的当前位置";二者不一致的场景见 3.6。

3.2 -L:逻辑路径(默认行为)

-L 打印 PWD 环境变量中的逻辑路径,即使它含有软链成分。通过软链 link 进入目录后实测:

$ cd /root/demo/pwd/link
$ pwd
/root/demo/pwd/link
$ pwd -L
/root/demo/pwd/link

cd /root/demo/pwd/link 之后,shell 把 PWD 记成了带软链名的 /root/demo/pwd/link,pwd -L 原样返回这个值。可见不带参数的 pwd(上一节)与 pwd -L 输出相同,印证帮助原文 "By default, pwd' behaves as if -L' were specified."。

💡 提示:-L 的全称是 logical。它不做任何文件系统检查,只翻译 PWD 变量,因此速度最快,代价是路径可能"名不副实"(软链场景)。

3.3 -P:物理路径

-P 把路径中所有软链解析掉,返回真实物理目录。仍在软链目录 link 中:

$ pwd -P
/root/demo/pwd/real

同一个位置,pwd -L 给 /root/demo/pwd/link,pwd -P 给 /root/demo/pwd/real——后者才是磁盘上真实存在的目录路径。

3.4 -L 与 -P 软链对照实测(含 /bin/pwd 对照)

本节把两个参数、两个实现在同一软链目录下放在一起对照,差异一目了然:

$ cd /root/demo/pwd/link
$ pwd
/root/demo/pwd/link
$ pwd -L
/root/demo/pwd/link
$ pwd -P
/root/demo/pwd/real
$ /bin/pwd
/root/demo/pwd/real
$ /bin/pwd -L
/root/demo/pwd/link
$ /bin/pwd -P
/root/demo/pwd/real
$ readlink -f .
/root/demo/pwd/real

逐条解读:内建 pwd 与 pwd -L 输出逻辑路径;pwd -P 解析出真实目录;/bin/pwd 不带参数就输出真实目录(它的默认是 -P),与内建 pwd 形成鲜明对比;readlink -f . 同样解析出真实路径,作为交叉验证。

💡 技术拓展:需要"真实物理路径"时,可选项不止 pwd -P 一个,常用命令对比如下——

命令原理/特点适用场景
pwd -P内建命令,解析当前目录的软链交互与脚本里取当前位置的真实路径
/bin/pwd独立进程,默认即 -P,走 getcwd 系统调用需要向内核求证真实位置、或排查 shell PWD 变量被污染的场景
readlink -f 路径解析任意路径(含文件)的全部软链,路径不必是当前目录解析指定文件/目录的真实路径
realpath 路径与 readlink -f 同源的 coreutils 工具,额外支持 -m(允许路径不存在)、-s(不解析末段)脚本里规范化用户输入路径

本文实测采用 pwd -P 取当前位置、readlink -f . 做交叉验证;解析"任意给定路径"而非"当前目录"时选 readlink -f。

3.5 内建 pwd 与 /bin/pwd 是两个实现

type -a 可以列出同名命令的全部身份,配合 dpkg 查询确认 /bin/pwd 的归属:

$ type pwd
pwd is a shell builtin
$ type -a pwd
pwd is a shell builtin
pwd is /usr/bin/pwd
pwd is /bin/pwd
$ which pwd
/usr/bin/pwd
$ ls -l /bin/pwd /usr/bin/pwd
-rwxr-xr-x 1 root root 35336 Aug 25 15:12 /bin/pwd
-rwxr-xr-x 1 root root 35336 Aug 25 15:12 /usr/bin/pwd
$ dpkg -S /bin/pwd
coreutils: /bin/pwd
$ dpkg -S /usr/bin/pwd
dpkg-query: no path found matching pattern /usr/bin/pwd
$ dpkg -l coreutils | tail -1
ii  coreutils      8.32-4.1ubuntu1.4 amd64        GNU core utilities

解读:type -a pwd 依次列出内建与两个磁盘路径;which pwd 只在 PATH 里找外部程序,返回 /usr/bin/pwd;两个路径大小一致(35336 字节),因为 Ubuntu 22.04 采用 merged-usr 布局,/bin 是指向 /usr/bin 的软链;dpkg -S 按软件包注册的规范路径查询,所以 /bin/pwd 能查到 coreutils: /bin/pwd,而 /usr/bin/pwd 报 no path found——不影响事实归属,dpkg -l coreutils 确认包版本为 8.32-4.1ubuntu1.4。

💡 提示:内建版存在的意义是零进程开销(不 fork 外部程序)且能感知 shell 自己维护的 PWD 变量;需要"内核视角的真实位置"时再动用 /bin/pwd。

3.6 错误场景与边界行为

内建 pwd 只认 -L、-P,传其他选项会报错。交互式终端下的报错格式实测(bash -ic 模拟交互 shell,grep 过滤交互初始化的提示行):

$ bash -ic 'pwd --bogus' 2>&1 | grep -v 'job control' | grep -v 'process group'
bash: pwd: --: invalid option
pwd: usage: pwd [-LP]

第一行是 bash 的报错(非法选项 --),第二行是内建 pwd 自带的用法提示,只接受 [-LP]。

另一个经典边界:当前目录被删除后。先进入 /root/demo/pwd/gone 再删掉它,看两个实现的反应:

$ mkdir -p /root/demo/pwd/gone
$ cd /root/demo/pwd/gone
$ rmdir /root/demo/pwd/gone
$ pwd
/root/demo/pwd/gone
$ /bin/pwd
/bin/pwd: couldn't find directory entry in '..' with matching i-node

内建 pwd 仍然"报出"已被删除的目录——因为它只是回显 PWD 变量,不做任何系统调用;/bin/pwd 则诚实地向内核求证,报出 couldn't find directory entry in '..' with matching i-node(父目录里已找不到匹配 i-node 的项)。随后 cd 出来即可恢复正常:

$ cd /root/demo/pwd
$ pwd
/root/demo/pwd

💡 提示:遇到"pwd 显示的目录明明不存在"的怪象,先用 /bin/pwd 求证——这正是两个实现的价值差异(见 3.4 拓展表)。

四、实战示例

4.1 脚本里获取并记录物理路径

日志、备份类脚本通常要记录"真实位置",避免软链路径在日后失效。用 pwd -P 直接取:

$ cd /root/demo/pwd/real && echo "current: $(pwd -P)"
current: /root/demo/pwd/real
$ pwd -P > /root/demo/pwd/where.txt
$ cat /root/demo/pwd/where.txt
/root/demo/pwd/real

第一条命令演示了命令替换 $(pwd -P) 拼进日志行的写法;后两条把物理路径重定向到 where.txt 再 cat 读回,确认落盘内容是真实目录 /root/demo/pwd/real 而非软链路径。

4.2 判断当前是否处于软链路径

比较 PWD 变量与物理路径是否一致,即可识别"当前是不是从软链进来的":

$ cd /root/demo/pwd/link
$ test "$PWD" = "$(pwd -P)" && echo physical || echo symlinked
symlinked

从软链 link 进入时二者不等,输出 symlinked;从 real 进入时相等,输出 physical。这个判断可用于脚本自检:要求必须在真实目录下运行时给出明确告警,而不是默默把数据写到软链目标里。

五、注意事项与常见问题

Q1:为什么 cd 过软链后,pwd 显示的是软链路径而不是真实目录? 内建 pwd 默认 -L 语义,直接返回 PWD 环境变量的值;cd 成功后 bash 会把"你敲的路径"(含软链名)记进 PWD。要真实目录请用 pwd -P(见 3.2、3.4 实测)。

Q2:pwd -P 和 readlink -f . 输出一样,该用哪个? 取"当前目录"的真实路径两者等价(见 3.4 对照)。解析任意给定路径(文件、深层软链)只能用 readlink -f;pwd -P 只针对当前位置,且不产生外部进程。

Q3:脚本里该用 pwd 还是 $PWD? 取值用 $PWD 更快(无子进程开销);但 $PWD 只是个变量,被人为篡改后不可信,关键场景用 pwd -P 或 /bin/pwd 向文件系统求证(见 3.6 的"已删目录"实测)。

Q4:/bin/pwd 和内建 pwd 为什么默认输出不一样? 默认语义相反:内建默认 -L(回显 PWD 变量),/bin/pwd 默认 -P(getcwd 求证真实位置)。两份 --help 原文都写明了这一点(见 2.2)。

Q5:pwd --bogus 为什么报 invalid option? 内建 pwd 只接受 -L、-P 两个参数,其他一律报 bash: pwd: --: invalid option 并提示 usage: pwd [-LP](见 3.6 实测)。长选项 --logical、--physical 只有 /bin/pwd 支持。

Q6:进入被删除的目录后,pwd 还能正常输出,是不是没受影响? 不是。内建 pwd 只回显变量,输出的是"过期路径";/bin/pwd 会报 couldn't find directory entry in '..' with matching i-node。此状态下建议立即 cd 到有效目录(见 3.6 实测与恢复)。

六、参考链接