如何将Bash中的相对目录名转换为可识别的绝对路径?
Bash中read读入的相对路径无法通过-d目录检测的解决方法
问题重现
当使用read命令读入相对目录路径时,路径无法被[ -d ]测试识别为有效目录,示例如下:
波浪号路径~/tmp的情况
corba@samwise:~$ read CMDLINE_FILENAME ~/tmp corba@samwise:~$ echo "$CMDLINE_FILENAME" ~/tmp corba@samwise:~$ if [ -d $CMDLINE_FILENAME ]; then echo "Valid directory!"; fi # 无输出,未通过目录检测
上级目录相对路径../tmp的情况
corba@samwise:bin$ read CMDLINE_FILENAME ../tmp corba@samwise:bin$ echo "$CMDLINE_FILENAME" ../tmp corba@samwise:bin$ if [ -d $CMDLINE_FILENAME ]; then echo "Valid directory!"; fi # 无输出,未通过目录检测
绝对路径可正常通过检测
corba@samwise:~$ read CMDLINE_FILENAME /home/corba/tmp corba@samwise:~$ echo "$CMDLINE_FILENAME" /home/corba/tmp corba@samwise:~$ if [ -d $CMDLINE_FILENAME ]; then echo "Valid directory!"; fi Valid directory!
单独执行if [ -d ~/tmp ]或if [ -d ../tmp ]能正常识别,但通过read读入变量后就失效,且仅针对波浪号的展开方法无法解决../、./这类相对路径的问题,该现象在MSYS2(Git Bash)和Ubuntu 22中均存在。
问题原因
- 波浪号路径:Bash仅会在命令行解析阶段自动展开波浪号,
read读入的内容是原始字符串,不会触发自动展开,因此[ -d ]检测的是字面量~/tmp而非实际的用户目录路径。 - ../相对路径:若路径实际存在但检测失败,大概率是变量引用时未加引号(路径含空格时会被拆分),或输入的路径包含隐藏字符(如换行、不可见字符),导致系统无法识别。
解决方法
方法1:用eval手动展开路径(适合信任输入的场景)
eval可以触发Bash的路径展开机制,处理波浪号和相对路径:
read CMDLINE_FILENAME # 展开路径,注意变量加引号避免空格拆分 expanded_path=$(eval echo "$CMDLINE_FILENAME") if [ -d "$expanded_path" ]; then echo "Valid directory!" fi
测试验证:
# 波浪号路径测试 corba@samwise:~$ read CMDLINE_FILENAME ~/tmp corba@samwise:~$ expanded_path=$(eval echo "$CMDLINE_FILENAME") corba@samwise:~$ if [ -d "$expanded_path" ]; then echo "Valid directory!"; fi Valid directory! # ../路径测试(在bin目录下) corba@samwise:bin$ read CMDLINE_FILENAME ../tmp corba@samwise:bin$ expanded_path=$(eval echo "$CMDLINE_FILENAME") corba@samwise:bin$ if [ -d "$expanded_path" ]; then echo "Valid directory!"; fi Valid directory!
注意:
eval会执行变量中的命令,仅在自己输入或信任来源的内容时使用,避免注入风险。
方法2:用realpath转换为绝对路径(更安全)
realpath可以将任何相对路径(包括~/、../、./)转换为规范化的绝对路径,且不会执行命令,安全性更高:
read CMDLINE_FILENAME # -m参数:即使路径不存在也生成规范化路径,适合先验证存在性的场景 expanded_path=$(realpath -m "$CMDLINE_FILENAME") if [ -d "$expanded_path" ]; then echo "Valid directory!" fi
额外优化:启用路径补全减少输入错误
使用read -e启用命令行编辑和自动补全,避免手动输入路径出错:
read -e -p "请输入目录路径: " CMDLINE_FILENAME expanded_path=$(realpath -m "$CMDLINE_FILENAME") if [ -d "$expanded_path" ]; then echo "Valid directory!" fi
内容的提问来源于stack exchange,提问作者CorbaTheGeek
相关产品推荐
相关产品推荐

