Shell 脚本里 cd 失败了,为什么后面的命令还在执行?

举报
yd_259541464 发表于 2026/11/04 12:41:43 2026/11/04
【摘要】 脚本经常先进入一个目录,再用相对路径读取或生成文件。如果 cd 失败,而后面的命令仍然运行,就可能在原来的目录里操作,结果和预期完全不同。例如,下面两行没有显式检查第一行的结果:cd -- "$target"printf '现在开始处理当前目录\n'当目标目录不存在或无法进入时,cd 会返回非零状态;如果脚本没有其他退出控制,第二行仍会执行。输出错误信息本身不会让普通 Bash 脚本自动停止...

脚本经常先进入一个目录,再用相对路径读取或生成文件。如果 cd 失败,而后面的命令仍然运行,就可能在原来的目录里操作,结果和预期完全不同。

例如,下面两行没有显式检查第一行的结果:

cd -- "$target"
printf '现在开始处理当前目录\n'

当目标目录不存在或无法进入时,cd 会返回非零状态;如果脚本没有其他退出控制,第二行仍会执行。输出错误信息本身不会让普通 Bash 脚本自动停止。

先确认目录切换成功

下面是一个可以直接保存为 Bash 脚本的例子:

#!/usr/bin/env bash
set -u

target="${1:?请传入目标目录}"

if ! CDPATH= cd -- "$target"; then
  printf '无法进入目标目录:%s\n' "$target" >&2
  exit 1
fi

printf '当前工作目录:%s\n' "$PWD"
# 在确认切换成功后,再执行需要相对路径的操作。

${1:?...} 会在参数缺失或为空时给出提示并退出。"$target" 的引号让包含空格、通配符等字符的路径作为一个参数;-- 用来结束选项解析。若目录名恰好是单独的 -,Bash 的 cd 会把它当作返回上一个目录;要进入当前目录下名为 - 的目录,应写成 ./-。

if ! ... 会在 cd 失败时进入错误分支,错误信息写到标准错误,随后以非零状态退出。这样后续命令只会在切换成功后运行。

为什么示例里设置了空的 CDPATH?

Bash 可以通过 CDPATH 指定查找相对目录的搜索路径。交互式终端中这可能方便,但脚本拿到相对路径时,非空 CDPATH 可能让它进入搜索路径中的同名目录。

示例里的 CDPATH= cd ... 只为这次 cd 提供空的 CDPATH,使相对路径按当前目录查找;绝对路径本来就不使用 CDPATH。如果脚本有意依赖 CDPATH,则应按实际需求决定是否保留。

set -e 能代替检查吗?

set -e 在不少简单命令失败时会使 Bash 退出,但它有例外:例如命令作为 if 条件,或处于某些 &&、|| 列表位置时,行为不同。对于“目录没切过去就不能继续”这样的关键前提,直接检查 cd 的结果更容易读懂,也更便于给出明确错误信息。

另外,执行脚本会在子进程中改变脚本自己的工作目录,不会改变调用它的终端所在目录。如果需要改变当前交互式终端的目录,应直接在该终端执行 cd;不要为了这个目的随意 source 不可信的脚本。

我用临时目录验证了示例:含空格和以连字符开头的目录可以进入;目录不存在、目标是普通文件或参数缺失时会返回错误。另设了 CDPATH 下的同名目录,确认示例仍选择当前目录中的目标。

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。