Linux cd命令从入门到精通:路径切换、磁盘管理与脚本避坑指南
2026/9/24 19:21:40 网站建设 项目流程

1. 为什么要把cd归到磁盘管理里

看到这个标题,估计不少人心里犯嘀咕:cd不就是切换目录吗?跟磁盘管理八竿子打不着吧。

其实把cd放进磁盘管理这个分类,仔细想想是有道理的。磁盘管理这一层,说白了就是跟存储、分区、挂载、目录打交道。你在Linux上插一块新硬盘,要分区、要格式化、要挂载到某个目录,挂载完之后呢?你得cd到挂载点里去看看文件有没有正常写入。你要清理磁盘空间,得先一个目录一个目录地cd进去,用du、df看看哪里占的磁盘最多。磁盘管理的起点,永远是先搞清楚自己在哪个目录、能去哪儿。cd命令的熟练程度,直接决定了你在磁盘管理和日常命令行操作里的效率。

另外还有一个冷知识,cd是shell内建命令,压根就不是一个独立的可执行文件。你运行which cd,大概率什么都查不到,因为它直接由bash、zsh这样的shell解释器处理的,不走PATH搜索那套流程。这一点和ls、cp这类外部命令有明显区别。明白了这一点,你就能理解为什么cd在某些特殊场景下行为和普通命令不太一样。

对于刚接触Linux的新手,cd是你敲进去的第二个命令——第一个通常是ls。对于干了两三年的运维和开发,cd早就敲成了肌肉记忆,一天可能要按几百次。但这篇文章想说的是:即便是这么基础的一个命令,里面依然有不少坑、不少技巧,值得摊开来讲透。

2. 先搞清楚绝对路径和相对路径,cd 才不算白学

2.1 从当前目录出发的“相对路径”与从根目录出发的“绝对路径”

很多人cd用不利索,问题不在cd本身,而是没搞懂路径的两种写法。这个概念如果没吃透,后面什么符号链接、脚本编写、定时任务全都会踩坑。

绝对路径,就是从根目录/开始写,一条路走到底。比如你要进/var/log这个目录,就是:

cd /var/log

这条命令不管你在哪个位置,都能直接到达目的地。绝对路径的好处是确定性强、可重复,坏处是比较长,敲起来累。

相对路径,就是从当前位置出发,去往目标目录的路线。比如你现在在/var/log里,想进/var/log/nginx,就可以直接:

cd nginx

不需要写一大串绝对路径。再比如你现在在/var/log/nginx里,想回到/var/log,那就可以:

cd ..

这里的..代表上一级目录。相对路径的好处是短、灵活,坏处是你一旦搞不清自己当前的位置,就很容易跑偏。

我见过不少新手在这个地方栽跟头:明明想进/usr/local/nginx,结果因为当前目录是/usr/local,就输入了cd nginx/x — 其实这样的写法从当前路径的下一级nginx的子目录x去找,如果/usr/local下没有nginx这个目录,自然就报错了。

两个常见错误习惯得改掉:

  • 依赖pwd确认当前位置后再写相对路径,而不是凭记忆瞎猜。
  • 不要把绝对路径和相对路径混着写,比如cd /var/log/../tmp这种写法虽然技术上成立,但可读性极差,纯粹给自己找麻烦。

2.2 特殊目录符号的完整清单

路径写法的核心,是掌握下面这几个特殊符号。我直接整理成一张表,日常使用频率从高到低排:

符号含义示例说明
.当前目录cd ./nginx单点几乎可以省略,偶尔用于脚本中强调当前位置
..上一级目录cd ..两点回到上一级,可以叠加,比如cd ../..向上两级
-上一个所在目录cd -在两个目录之间来回横跳,极其好用
~当前用户的家目录cd ~等价于直接敲cd回车
~user指定用户的家目录cd ~mysql需要该用户存在,否则会报错
/根目录cd /所有路径的起点

这几个符号里,我觉得值得单独拎出来重点说的是cd -。它记住的是你上一次所在的目录,利用的是shell里的环境变量OLDPWD。这个功能在什么场景下最爽?比如你在写配置文件,先cd到/etc/nginx去改配置,然后需要去/var/log/nginx看日志文件,看完了又想切回去继续改配置。这时候你只需要敲cd -,连目录名都不用输入,直接弹回上一个工作目录。来回切几次,你会真切感觉到这个设计的巧妙。

还可以告诉你一个小细节:cd -执行时会自动把目标路径打印在终端上。这方便你确认自己到底切到了哪儿,也方便你在脚本里捕获这个值。如果你不想看到这行输出,可以用cd $OLDPWD代替,效果一样但不打印。

3. cd 命令的完整用法与返回机制

3.1 cd 的完整语法与三种调用方式

正式地讲,cd命令的语法范例如下:

cd [-L|[-P [-e]] [-@]] [dir]

先别被这一串吓到,平时你基本用不到这么复杂的组合。最常用的其实只有三种调用方式:

第一种,直接不带参数:

cd

不带任何参数时,cd会把当前目录切换到当前用户的家目录。如果你用root登录,就回到/root;用普通用户,就回到/home/用户名。这是最快捷的“回血”方式,比敲cd ~还省一个字符。

第二种,带一个路径参数:

cd /some/path

这个不用多说,目标路径可以是绝对路径也可以是相对路径。需要提醒的是,路径里不要混入空格,如果确实有空格,必须用引号包起来。比如进入名为My Documents的目录,得写成cd "My Documents"或者cd My\ Documents,直接裸敲空格会被当成两个参数。

第三种,带特殊符号参数:

cd - # 回到上一个目录 cd ~ # 回到当前用户家目录 cd ~user # 回到指定用户的家目录 cd .. # 回到上一级目录

这三种调用方式覆盖了日常百分之九十九以上的使用场景。

3.2 CDPATH 环境变量与逻辑路径、物理路径的坑

关于cd命令,有两个比较隐蔽的知识点,网上很多教程不会提,但实际工作中踩到会困惑半天。

第一个是CDPATH环境变量。它类似于PATH变量,但作用是给cd命令提供一个搜索路径列表。当你执行cd abc,而当前目录下没有abc这个子目录时,shell会按CDPATH里定义的一组目录逐一查找,看哪个目录下面有abc。如果你设置了:

export CDPATH=:/etc

那么你在任何目录下执行cd nginx,shell都会先看看当前目录有没有nginx,如果没有就去/etc下找。这个变量在某些环境下会被系统预设,导致出现“灵异现象”——明明当前目录没有这个子目录,cd却成功切到了别处。遇到这种情况,可以运行echo $CDPATH检查一下,不需要的话用unset CDPATH取消。

第二个是符号链接的逻辑路径和物理路径问题。假设/tmp/data是指向/mnt/storage/2024data的符号链接,你执行:

cd /tmp/data

此时你人已经在/mnt/storage/2024data里了,但shell里的PWD变量记录的仍然是/tmp/data这个逻辑路径。直接运行pwd,显示的是/tmp/data;运行pwd -P,才会显示物理路径/mnt/storage/2024data。

这个问题在写脚本的时候特别坑。因为有些脚本靠pwd获取当前目录,然后基于这个路径去引用相对文件。如果你通过符号链接进去的,拿到的是逻辑路径,一旦脚本把路径当作真实路径去拼接,可能就找错文件了。解决办法是,在脚本需要精确路径时,用pwd -P取物理路径。另外,cd -P /tmp/data可以直接把当前目录切到物理路径,PWD变量也直接记录真实路径。

4. 实操场景:从磁盘挂载到日志排查,cd 怎么用得飞起

4.1 挂载新磁盘后的目录切换操作流

说回磁盘管理这个主题。假设你给服务器加了一块新硬盘,按常规流程走一遍,你会发现cd在里面扮演的角色远比想象中多。

第一步,查看系统是否识别到新磁盘,输入lsblk或者fdisk -l,确认新磁盘的设备名,比如/dev/sdb。这是纯粹的磁盘操作,还没用到cd。

第二步,分区和格式化。前面这些都在系统层面操作,不需要进入特定目录。第三步,创建挂载点并挂载。这里就要用到cd了。比如你准备把新磁盘挂到/data目录,得先确认/data存在。不存在就创建:

ls -ld /data

如果提示不存在,继续:

sudo mkdir -p /data

然后挂载:

sudo mount /dev/sdb1 /data

挂载完成,接下来要验证。这时候cd的用武之地就来了:

cd /data ls -la

你会发现在/和/data这两个目录下看到的lost+found目录不一样——挂载ext4文件系统的磁盘根目录天然有个lost+found目录。如果你cd进一个刚挂载的空盘,却看不到lost+found,那说明你挂载可能失败了,或者误挂到了别的地方。这个细节在排查磁盘挂载问题时很实用。

然后你可以cd进/data的子目录做读写测试:

mkdir /data/test cd /data/test touch hello.txt ls -l

整个流程走下来,cd看似只是“进入目录”这一个动作,但实际上它是验证挂载结果、确认文件系统可读写的关键操作。如果没有cd进去看,你都不知道挂载是否成功。

4.2 日志目录、大文件目录切换的日常习惯

再举一个运维日常里非常高频的场景:排查日志和清理磁盘空间。

登录服务器第一件事,通常就是进日志目录。大部分人习惯直接敲:

cd /var/log

然后ls看有哪些日志。但高手会稍微加快一下效率,比如知道nginx日志在/var/log/nginx下,就直接一条命令到位:

cd /var/log/nginx && ls -lh access.log error.log

这里用&&把cd和ls串起来,一条命令完成“进入目录+查看文件”两个动作。&&表示只有当前一条命令执行成功才继续执行后一条。这种串法是cd命令在脚本和日常操作里最常见的组合用法之一。

但是这里有一个习惯必须养成:写脚本时,尽量不要依赖cd!这是我在生产环境里踩过坑后得出的血泪教训。原因有三:

  • 脚本里cd之后,如果后续某条命令执行失败,脚本会因为当前目录已经改变而继续在错误的位置运行,结果不可预测。
  • 如果脚本被并发执行,或者被别的地方调用,cd会改变全局的当前目录状态,可能影响其他逻辑。
  • 更稳妥的做法是,脚本内部统一使用绝对路径,或者用子shell把cd包起来:
(cd /var/log/nginx && grep "ERROR" access.log)

这样cd只在子shell内生效,不影响外部脚本的当前目录。

日常在终端操作时,还有一个实用习惯:在磁盘告警时,要快速定位哪个目录占用最大,可以先cd到根目录或挂载点,然后一层层找:

cd / du -h --max-depth=1 . | sort -hr | head -20

这里du命令会输出每个一级子目录的占用大小,看到哪个目录占用大,就cd进去再执行同样的命令。这种“cd + du + sort”的组合,是定位磁盘占用的标准操作流程。如果你熟练掌握cd的各种用法,这个排查过程会非常顺滑。

另外,批量处理多个目录时,不需要反复cd。很多人习惯进入目录一处理完就cd回上一级,再进入下一个目录。其实完全可以在一个目录里用绝对路径操作所有目标,或者用find命令一次性搞定。比如要查找所有超过1GB的大文件:

find / -type f -size +1G -exec ls -lh {} \; 2>/dev/null

find的-exec里面会自己处理,不需要你cd来cd去。命令行的哲学是用工具组合替代无谓的目录跳转,效率高得多。

4.3 用 cd 组合其他命令的高频实战片段

除了上面说的&&连接,我再分享几个高频的cd组合片段,都是生产环境下实测好用的。

快速回到项目的某个固定目录。不少开发者的做法是给常用目录设置别名,在~/.bashrc里加一行:

alias proj='cd /home/user/work/my-project/src'

以后敲proj就直达项目目录。类似的,还可以给日志目录、配置目录设置别名。别小看这个习惯,长期积累下来能省大量时间。

临时需要一个目录保存文件,可以这样:

mkdir -p /tmp/backup_$(date +%F) && cd $_

这里$_是上一个命令的最后一个参数,也就是刚创建的目录路径。cd $_可以直接切进去。这个技巧比反复用上下箭头翻历史命令要快得多。

在两个相关联的目录之间来回切换,比如配置文件目录和工作目录,用cd -的技巧我在前面说过。如果觉得只记一个“上一个目录”不够用,还可以借助pushd和popd来实现多目录栈管理:

pushd /etc/nginx pushd /var/log/nginx pushd /usr/local/src dirs

pushd会把当前目录压入目录栈,然后切换到新目录。用popd可以按逆序弹栈并切换回去。dirs列出当前栈内容。这个组合在需要同时在多个目录之间穿梭时,比反复cd和cd -更高效。

5. 常见问题排查与避坑实战

5.1 报错速查表

日常工作里,cd命令最常见的报错无非下面几种,我直接把原因和解决办法整理成表:

报错信息原因解决办法
bash: cd: xxx: No such file or directory目标目录不存在,或者相对路径写错用ls确认路径拼写,检查当前位置
bash: cd: xxx: Permission denied当前用户无权限进入该目录检查目录权限,必要时sudo切换或使用有权限的用户
bash: cd: xxx: Not a directory目标路径不是目录,而是一个普通文件用ls -ld确认类型,别拿文件当目录进
cd: HOME not set用户家目录环境变量未定义手动set HOME=/home/用户名,多见于非正常登录会话
bash: cd: 参数太多路径中包含未转义的空格用引号包住路径:cd "My Documents"

5.2 用 sudo 切换用户后目录问题的迷思

还有一个很有意思的场景,很多人会困惑:为什么我用su切换到root后,当前目录还是原来那个目录?

先说su和su -的区别。不带-的su,会切换到目标用户,但保留当前目录、环境变量等一系列状态。带-的su,会开启一个全新的登录会话,类似于该用户重新登录系统,目录默认回到该用户的家目录。

举个例子,你是一个普通用户,当前在/home/user/data目录下,执行sudo su后,你依然停留在/home/user/data,而不是root的家目录/root。如果你执行sudo su -,那么就会跳到/root。

理解这个区别很重要。有些情况下,你确实需要保留当前目录,比如在一个临时目录里处理文件,切换root后想继续在这个目录操作。这时候用不带-的su就正好。另一些情况下,你希望隔离环境,获得干净的root登录环境,用su -更合适。

与这个类似的是sudo执行时的目录问题。你运行sudo ls,因为sudo默认会保留当前工作目录,所以执行结果和你直接ls差不多。但sudo -i会模拟一个root的完整登录环境,目录会切到/root。

5.3 脚本中 cd 失败时如何防止错误扩散

写shell脚本时,cd命令有个隐蔽的“坑”——它如果失败了,默认不会终止脚本执行。比如下面这段脚本:

#!/bin/bash cd /nonexistent-directory rm -rf *

如果/nonexistent-directory不存在,cd会失败,但脚本不会停下来,而是继续执行rm -rf *。此时脚本仍然停留在调用者原来的目录,删除操作就会作用于调用者目录下的所有文件。这个后果有多严重,不用我多说。

完善的写法有几种:

  • 用set -e,任何一个命令返回非零状态就立即退出脚本:
#!/bin/bash set -e cd /nonexistent-directory
  • 或者显式判断cd是否成功:
#!/bin/bash if cd /nonexistent-directory; then rm -rf * else echo "无此目录,停止操作" >&2 exit 1 fi
  • 或者用||把失败操作挂在后面,最简单的防呆写法:
cd /some/dir || exit 1

这种习惯一定要养成。我在带团队的时候,要求所有脚本里的cd都必须带错误处理。原因就是这类问题在测试环境可能永远不暴露,一旦上了生产,遇到目录不存在的一次意外,就可能引发数据浩劫。

5.4 Tab 补全和引号使用的细节

最后说几个谈不上是“问题”但能显著提升效率的细节。

第一个是Tab键补全。Linux终端里按Tab键可以自动补全路径。但你得知道两个层次:按一次Tab,如果匹配唯一,自动补全完整路径;如果匹配多个,再按一次Tab会列出所有可能项。比如你输入cd /var/l,按Tab,系统会尝试补全成/var/log,如果/var下面有其他以l开头的目录,第一次按键没反应或只补全一部分,按两下就列出所有候选。这个操作在长目录名和带版本号的目录之间切换时,价值巨大。

第二个是目录名里有空格的处理。Linux支持带空格的目录名,但这在命令行操作里非常容易出错。我的建议是:自己创建目录时,尽量别用空格,用下划线或中划线代替。如果确实碰到了别人创建的带空格目录,用Tab补全最省心——终端会自动帮你转义成带反斜杠的格式,不需要自己手动加引号。

第三个是关于cd的“隐形输出”问题。在shell脚本里,如果你把cd放在变量替换或者命令替换中,要特别注意是否会把输出带入其他命令。比如:

cur_dir=$(cd /some/dir && pwd)

这个写法的意思是先切换到目标目录,然后把pwd的结果赋值给cur_dir。这里cd后面的路径如果错了,&&后面的pwd不会执行,cur_dir就为空。这种写法本身没问题,但要求你对每一步的返回状态有清晰的认识。

6. 回归命令行本质,把 cd 变成你的肌肉记忆

写到这里,我想聊一点个人体会。接触Linux这些年,见过不少刚入行的同事,把注意力放在各种花哨工具上,比如各种终端模拟器的标签页、远程管理的面板、图形化的文件管理器,却连最基本的cd和相对路径都掌握得不扎实。等真正要写脚本、排查线上问题的时候,才发现基本功薄弱带来的掣肘有多大。

cd命令再简单,它也是你和整个Linux文件系统打招呼的方式。每一天的运维工作,从cd进入第一个目录开始;每一次的故障排查,也要靠cd绕到关键路径下面才能定位问题。这个命令熟练到什么程度才算过关?我的标准很简单:闭着眼睛知道自己在哪个目录,知道去哪儿要多久,知道用相对路径还是绝对路径更顺手,遇到符号链接能立刻反应过来是不是隐藏了真实路径。

也有个值得坚持的日常习惯,就是每次命令行要进入某个目录前,先花零点几秒想一下:我是直接敲绝对路径快,还是先cd再一步一层进更快?虽然这听起来有点较真,但长年累月,省下的时间和减少的错误是客观的。尤其是配合Tab补全和CDPATH之后,整个操作节奏会顺滑很多。

最后再分享一个小技巧:如果你经常要在多个深度路径之间切换,试着给这些路径在~/.bashrc里定义变量。比如:

export NGX_LOG=/var/log/nginx export NGX_CONF=/etc/nginx

之后你就能这样用:

cd $NGX_LOG cd $NGX_CONF

变量名的语义清晰,比直接敲一长串路径好记忆,也比alias更灵活——因为变量还能用在其他命令里,比如tail -f $NGX_LOG/error.log。这是我个人最常用的实践之一,建议你试试看。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询