这篇文章专门聊一个看起来特别基础、但问的人特别多的问题:Linux怎么查看当前路径。核心命令就是pwd,全称是 print working directory,翻译过来就是“打印当前工作目录”。不管你是刚装好一个 Linux 虚拟机、刚开始用云服务器,还是准备在写脚本时确定文件位置,知道当前处在哪个目录,永远都是第一步。这篇内容我会从命令本身讲起,把pwd的两个常用参数、在脚本里的典型用法、和路径有关的坑、以及我自己踩过的一些经验都整理出来。适合刚入门 Linux 的新手,也适合那些已经在用了但偶尔被符号链接、环境变量搞糊涂的同学。
1. 项目背景:为什么“查看当前路径”是很多人绕不过去的坎
1.1 路径到底是什么
在 Linux 里,一切文件都挂在根目录/下面,系统通过目录结构把文件组织成一个树状结构。你每打开一个终端,Shell 都会记录你现在“站在”这棵树的哪个节点上,这个节点就是当前工作目录(current working directory)。命令行提示符里有时会显示路径,有时不显示,但不管你看到看不到,Shell 内部始终维护着一个“当前路径”的概念。
这个概念之所以重要,是因为 Linux 的相对路径全靠它来计算。你在终端里输入ls file.txt,系统不会全盘搜索 file.txt,而是默认在当前目录里找。你要是输入./start.sh,这里的.代表的就是当前目录。所以当你执行了某个命令但“找不到文件”的时候,第一反应就应该是:先搞清楚当前路径是不是我以为的那个路径。
1.2 为什么这个问题总是有人问
我见过很多刚接触 Linux 的人,第一个问题不是“怎么列出文件”,而是“我现在在哪”。原因很真实:图形界面用多了,我们习惯了“打开资源管理器就能看到地址栏”。但 SSH 连上服务器之后没有桌面,只有一行黑底白字的命令行,没有地址栏,人容易失去方向感。这时候pwd就是那个“我在哪”的答案。
还有一个容易引发疑问的场景是别人给的教程:“你先 cd 到某个目录”。你照着敲了,但不知道有没有成功,或者想确认一下是不是真的进去了,这时候就需要pwd来给你吃一颗定心丸。说白了,它解决的是一个空间定位问题,是所有命令里最不起眼、但最不能缺失的一个。
1.3 这篇文章适合谁
如果你是纯新手,刚装好 Ubuntu、CentOS 或者某个国产 Linux 发行版,这篇文章可以从零教会你pwd的正确打开方式。如果你已经会用ls、cd这些命令,但对pwd -P和pwd -L的区别不大确定,或者写脚本时拿到的路径情况和你想象的不一样,这篇文章也能帮上忙。我不会讲那些不切实际的冷门用法,只讲平时真的用得到的东西。
2. 核心命令解析:pwd 到底怎么用
2.1 最基础的用法:直接敲 pwd
在终端里输入pwd,回车,屏幕上会输出一串绝对路径。所谓绝对路径,就是从根目录/开始的完整路径,比如/home/ubuntu/projects。它不会因为你在哪个目录而改变含义,任何时候看到这串路径,你都能直接定位到对应的目录。
$ pwd /home/ubuntu/projects就这么简单三个字母,没有参数也能用。你不需要sudo,不需要安装任何东西,它是 Bash、Zsh、Sh 这些主流 Shell 内置的命令,也存在于大多数 Linux 发行版中。普通用户在自己的目录里可以用,在系统目录里也可以用,除非你连登录权限都没有,否则不存在“pwd 命令不存在”这种问题。
这里有一个关键点要强调:pwd输出的是“当前 Shell 的工作目录”,而不是“当前执行的脚本文件所在目录”。这两者在交互式终端里常常一样,但在脚本里可能不一样。很多人写脚本踩坑,就是没搞清楚这个问题。我后面会详细展开。
2.2 常用的两个选项:-L 和 -P
pwd最常见的两个选项是-L和-P。默认情况,也就是你直接敲pwd,大多数发行版用的是-L逻辑路径,但也有个别环境不一样。这两个参数处理的是同一个问题:当你所在目录是通过符号链接(symlink,类似 Windows 的快捷方式)进入的,pwd应该显示链接本身的路径,还是链接背后真实目录的路径。
先看一个例子。假设存在一个符号链接/tmp/link-to-project,它指向/home/ubuntu/project。如果你 cd 进了这个链接路径,直接敲pwd,很可能输出的是/tmp/link-to-project,这是逻辑路径(Logical)。而pwd -P会一路解析到底,输出真实路径/home/ubuntu/project。
$ cd /tmp/link-to-project $ pwd /tmp/link-to-project $ pwd -L /tmp/link-to-project $ pwd -P /home/ubuntu/project这两个参数说实话平时用得不多,但遇到下面这类场景就特别关键:你在一个符号链接目录里用相对路径引用了文件,结果/tmp/link-to-project被删掉重建,路径就断裂了;或者你启动一个服务,服务把自己记录的工作目录写进了日志,但你怀疑它记的是链接路径而不是真实路径,导致排查问题找错了地方。这时候pwd -P就能帮你看到铁板钉钉的真实路径。
2.3 和其他命令搭配的真实场景
pwd虽然是个“查询”命令,但它经常被组合进其他操作里。最常见的一个场景是复制当前路径:你不想手打一长串绝对路径,可以直接把pwd的结果当作命令的输入。比如要把当前目录下的所有文件复制到/backup:
$ cp "$(pwd)"/*.log /backup/再比如你想往文本文件里记录本次操作的路径,方便事后追溯:
$ echo "当前工作目录:$(pwd)" >> run.log在命令行里用$(pwd)包起来,意思就是“先执行 pwd,把它的输出作为字符串放在这里”。这比手动敲目录名安全得多,尤其是目录名里有空格、特殊字符的时候,用双引号包住$(pwd)能避免很多坑。
3. 实操过程:从登录到脚本,我平时是怎么用 pwd 的
3.1 登录后的第一件事
我自己的习惯是,每次 SSH 登录服务器之后,先不急着干活,只敲两个命令:pwd和ls。原因很简单,服务器可能是多人共用的,上一次别人登录后可能把目录切到了奇怪的位置,我直接执行命令可能会在错误的目录里产生文件。先pwd确认当前位置,再ls看看这个目录里有什么,心里就踏实了。
如果你发现登录后不在自己家目录,也不需要慌。用cd ~回到当前用户家目录,或者用cd /home/用户名直接定位到家目录。然后再次用pwd确认:
$ cd ~ $ pwd /home/ubuntu这时候你输出的路径一般就是/home/用户名,而 root 用户则是/root。看到这个路径,说明你已经回到了自己的地盘,可以安心折腾了。
3.2 在 Shell 脚本中获取当前目录
这是pwd最容易出问题的地方,也是脚本新手和运维老手都绕不开的。假设你写了一个脚本/home/ubuntu/deploy/run.sh,脚本内部有一条命令要读取同目录下的配置文件config.ini,你可能会这么写:
#!/bin/bash cat config.ini这个写法在“你手动进入/home/ubuntu/deploy后执行./run.sh”的时候没问题,因为当前目录确实是脚本所在目录。但如果你在/tmp下执行/home/ubuntu/deploy/run.sh,那么cat config.ini找的是/tmp/config.ini,而不是脚本旁边的config.ini。这就出现了典型的“脚本换个地方执行就报错”的怪现象。
想让脚本无论从哪里被调用都能找到自己的文件,正确做法是先获取脚本所在目录,再基于这个目录去引用文件。我自己常用的是这样:
#!/bin/bash SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" cat "$SCRIPT_DIR/config.ini"我来拆解一下这行经典写法,dirname "$0"是提取脚本路径中的目录部分,$0指的是脚本本身的路径。然后用cd切到这个目录,再用pwd拿到它的绝对路径。注意这里我没有直接用pwd,而是先cd再pwd,就是为了把相对路径转换成绝对路径,避免后面cd到其他目录后找不到这个路径。
3.3 在 find、rsync、tar 等命令中确认路径
再举一个我实际运维中经常遇到的例子。我想把某个项目目录里 3 天前修改过的文件打包:
$ find "$(pwd)" -type f -mtime -3这里把$(pwd)传给了 find,这样输出的结果就是绝对路径全列表,而不是相对路径。为什么要这样做?因为当你后面要拿这个列表去 rsync、tar 或者写进日志的时候,绝对路径信息更完整,也方便其他同事直接复制使用。
在 rsync 场景也一样:
$ rsync -av "$(pwd)/" remote-server:/backup/project/$(pwd)/末尾带斜杠,这表示“当前目录下的内容”,rsync 同步时就只会同步目录内部文件,而不会多包一层同名目录。这个细节很多人第一次用 rsync 会踩坑,如果你不确定当前目录是什么,加上$(pwd)至少能保证源头是对的。
4. 与路径相关的常用命令补充
4.1 切换目录 cd 与路径的关系
pwd和cd的关系就像“地图”和“走路”:cd负责改变位置,pwd负责汇报位置。我建议新手把这两个命令放在一起练。先cd /etc,再pwd看看是否切到了/etc;再cd ..,再pwd看看是不是回到了上一层。
cd ..中的..代表上一级目录,这是相对路径的用法。相对路径是依赖当前工作目录的,所以每次执行完cd之后,你的“坐标系原点”就变了。这时候如果你还凭着之前的记忆去理解文件位置,很容易出现偏差。我见过很多次这样的场面:一个人进入子目录后执行rm -rf 某个文件夹,本意是删项目里一个旧目录,但因为没先pwd确认,实际在错误的目录里执行了删除操作。谨慎的做法是:在任何有风险的命令执行之前,先pwd确认一下当前路径,成本极低,收益极高。
4.2 查看文件绝对路径的其他方法
除了pwd,Linux 里还有一些能间接告诉你路径的方法。比如用ls -l查看某个文件时,输出结果不会直接给出绝对路径,但可以用readlink -f解析符号链接:
$ readlink -f /tmp/link-to-project /home/ubuntu/project还有realpath命令,也能输出一个路径的绝对形式:
$ realpath config.ini /home/ubuntu/projects/config.ini这两个命令在处理深层链接、相对路径转换时很好用。不过日常使用频率最高的仍然是pwd,毕竟它就是为了“汇报当前位置”而生的。用熟了之后,你会形成一种肌肉记忆:拿不准自己在哪,先敲pwd;脚本里要引用文件,先pwd``确认基准目录;准备执行有风险的操作,再pwd``兜底。
5. 常见问题与排查技巧实录
5.1 问题:pwd 显示的路径和 ls 对不上
有人遇到过这种情况:pwd显示在/home/ubuntu,但ls列出来的内容和印象里完全不同。这时候先别怀疑系统坏了,要思考两个可能。第一,ls列出的可能不是你想的目录,因为你可能设置了alias,把ls替换成了ls /somewhere。用type ls可以看到别名定义:
$ type ls ls is aliased to `ls --color=auto'第二,你当前所在的这个目录,可能是一个符号链接,它的“名字”和“真实位置”不是一回事。这就会让人觉得路径对不上。比如/home/ubuntu本身可能不是真实目录,而是链接到别的位置。用pwd -P就能看到真实路径,再用ls -ld /home/ubuntu看看这个路径是不是链接,问题就能查清楚。
5.2 问题:符号链接目录下 pwd 到底该显示什么
这个话题前面已经提过,但我想单独再说一次,因为它是问得最多的问题之一。在 Bash 里,默认的pwd行为是逻辑路径,也就是说如果你通过符号链接进入一个目录,pwd显示的是链接路径。但如果你用cd进入符号链接后在子目录里再执行pwd,行为可能让你困惑。
一个实际的例子:/www是指向/data/wwwroot/default的符号链接。你cd /www后,pwd可能显示/www,也可能显示/data/wwwroot/default,取决于你的 Shell 配置。如果希望在cd的时候就把符号链接解析成真实路径,可以在 Bash 里设置:
$ set -P或者在cd后使用pwd -P来看真实路径。对于做 Web 运维的人来说,搞清楚这个区别很重要,因为 NGINX、PHP-FPM 这类服务记录的路径会直接影响日志排查。我曾经排查一个“文件明明存在但页面 404”的问题,最后发现是服务进程的真实工作目录和符号链接路径不一致,类似这种场景,pwd -P就是你最直接的取证工具。
5.3 问题:脚本里拿到的是相对路径,怎么转成绝对路径
脚本里经常出现./开头的路径,转成绝对路径的通用方法前面已经提过。我再补充一种使用 Bash 内置参数扩展的写法,在某些场景下更简洁:
$ p=${0%/*} $ p=${p:-.} $ SCRIPT_DIR=$(cd "$p" && pwd)第一行把$0的最后一个斜杠和后面的内容去掉,相当于取目录部分;第二行防止路径为空时回退到当前目录;第三行再用cd && pwd变成绝对路径。这种写法算是我个人比较喜欢的方案,因为它既处理了“脚本路径没有斜杠”的情况,也处理了“相对路径变成绝对路径”的需求。
如果你的脚本是在 systemd 服务里启动的,还要注意:systemd 默认的工作目录可能是/,而不是脚本所在目录。这时候脚本里直接执行pwd得到的是/,如果你指望它拿到脚本目录,就会失败。在 systemd unit 文件里可以显式加上WorkingDirectory=来指定工作目录,这是另一个和路径密切相关的坑,值得记在笔记里。
6. 扩展:和环境变量、路径显示相关的细节
6.1 PWD 环境变量
你可能不知道,pwd命令输出的大多数内容其实来自一个环境变量:PWD。在 Bash 里,这个变量由 Shell 自动维护,每次执行cd时更新。你可以用echo $PWD直接查看:
$ echo $PWD /home/ubuntu注意大小写,环境变量名PWD是大写,pwd命令是小写。这是两样东西,但内容通常是关联的。你甚至可以手动设置PWD变量,但我不建议这样做,因为会造成 Shell 内部状态不一致。在脚本中,如果你想获取当前目录但不希望启动一个外部命令,可以用echo "$PWD",它比调用pwd命令稍微快一点,因为它是纯 Shell 内置变量读取,不用启动子进程。当然,在交互式终端里,两者的差异可以忽略不计。
6.2 OLDPWD:上一个目录的快捷记忆
和PWD配套的还有OLDPWD,它记录的是你“上一个工作目录”。当你执行cd -时,Bash 就是通过OLDPWD实现的。这个变量对路径切换很有用,但它也很容易被忽略。比如你在脚本中保存了OLDPWD,结果后面又执行了别的cd,OLDPWD就变了,你的“上一个目录”已经不是你以为的那个目录了。
所以在脚本中如果需要长期记住某个路径,不要依赖PWD和OLDPWD这些会变的环境变量,应该把它存到自定义变量里。这一点我在写自动化部署脚本时反复提醒自己:临时存储路径用只读变量,命名尽量清晰,比如BASE_DIR、CONFIG_DIR,避免脚本一长、逻辑一复杂就分不清哪个变量对应哪个路径。
6.3 自定义命令提示符显示路径
既然聊到路径,顺便说一下如何让提示符一直显示当前路径,这样能减少敲pwd的次数。Bash 的提示符由PS1控制,常见的配置是把\w(当前路径)或\W(只显示最后一级目录名)放进 PS1:
$ export PS1='\u@\h:\w$ '改完之后,命令行你的提示符会变成类似ubuntu@server:/home/ubuntu$的样子,当前路径一目了然。如果你用的是 Zsh,提示符配置方式不同,但思路一样:让 Shell 替你显示路径,而不是每次手动查。这不算偷懒,而是提高效率的正道,毕竟pwd的价值不只是执行命令,更是让你在任何时刻都有“方向感”。
7. 几个我实际踩过、值得记录的坑
7.1 在管道和子 Shell 里 pwd 可能不是你看到的值
管道、括号子 Shell 里执行pwd,结果一般不变,但有一种情况要注意:如果你在脚本里写了cd /somewhere,然后又用管道调用了一个子进程,子进程里的当前目录可能不是你cd之后所在的目录,因为管道两端的命令通常是在子 Shell 中执行的。比如:
$ cd /tmp && echo "当前目录: $(pwd)" | cat这个例子没问题,因为cd和echo在同一个子 Shell 里。但如果写成:
$ echo "当前目录: $(pwd)" | cat $ cd /tmp你看到第一行输出的路径,还是执行cd之前的路径。这不是 Bug,而是 Shell 执行顺序和理解的问题。记住一个原则:管道左侧的命令会在子 Shell 中执行进程复制,它里面的cd不会影响父 Shell 的当前目录,除非你使用{ cd /tmp; pwd; }这样的组合语法。类似这种问题,稍微不注意就容易在脚本里出怪事。
7.2 目录被删除后 pwd 显示的路径可能已经不存在
还有一类问题:你cd进一个目录后,这个目录被另一个进程删除或者重命名了,此时你执行pwd,Bash 通常仍然显示旧的路径,但ls会报错说目录不存在。很多人会怀疑pwd在骗人,其实不是。pwd反映的是 Shell 内部记录的路径逻辑值,而文件系统里可能已经发生了改变。用ls -ld验证一下就能确认。
这类情况常见的场景是临时目录/tmp下被定时清理,或者同事正在同一台机器上整理目录。遇到这种“路径存在但访问不了”的情况,最简单的办法是cd ~先回到安全目录,然后再重新定位。
7.3 不要在脚本中过度依赖 pwd 结果做字符串拼接
最后再提醒一个我见过无数次的写法规避问题:很多人习惯在脚本里这样写:
DIR=$(pwd) rm -rf "$DIR/backup"这种方式本身没问题,但如果路径中包含空格或特殊字符,而脚本里没有用双引号包住变量,就会导致命令解析出错。再一个隐蔽的问题是,如果DIR正好是根目录/,那"$DIR/backup"就变成了/backup,而不是你想删除的当前目录/backup。所以,执行删除类操作前,先用echo打印将要处理的路径,确认无误后再执行,这是我多年运维养成的习惯,也建议你养成。
用pwd确认当前路径是 Linux 里最基础的一步,但最基础的操作往往隐藏着最多的细节。简单的三个字母,背后有逻辑路径和物理路径的区别,有环境变量和 Shell 状态的关联,有交互式终端和脚本场景的差异。把这些细节搞清楚,后续学习文件操作、写脚本、排查问题时都会顺畅很多。
我个人在实际使用中的体会是:不要把pwd只当成一个查询命令,而是把它当成一种“定位习惯”。每次进入一个新的陌生目录,先pwd;每次写一个有删除、覆盖、移动操作的命令,先pwd;每次写脚本要用配置文件,先确认基准目录。习惯形成之后,你踩路径相关坑的次数会显著下降。希望这篇内容能帮你把pwd用得明明白白,不再被“当前路径到底在哪”这种问题绊住脚。