我有一个文件,说:~/cwd
。该文件的内容是一行:
~/tmp
我想要cd
到这个(〜/ tmp)目录。我在尝试:
> cd `cat ~/cwd`
得到了:
-bash: cd: ~/tmp: No such file or directory
为什么RELATIVE路径失败?当~/cwd
的内容是绝对路径时 - 它可以工作。
答案 0 :(得分:4)
这不是相对路径的问题 - 这是因为shell评估模型在参数扩展之前进行了扩展。回到评估过程的最初阶段,使用eval会引入安全漏洞 - 所以如果真的需要支持这个(我强烈地认为这是一个坏主意),那么就是一个安全的实现(针对具有getent
命令可用)如下所示:
expandPath() {
local path
local -a pathElements resultPathElements
IFS=':' read -r -a pathElements <<<"$1"
: "${pathElements[@]}"
for path in "${pathElements[@]}"; do
: "$path"
case $path in
"~+"/*)
path=$PWD/${path#"~+/"}
;;
"~-"/*)
path=$OLDPWD/${path#"~-/"}
;;
"~"/*)
path=$HOME/${path#"~/"}
;;
"~"*)
username=${path%%/*}
username=${username#"~"}
IFS=: read _ _ _ _ _ homedir _ < <(getent passwd "$username")
if [[ $path = */* ]]; then
path=${homedir}/${path#*/}
else
path=$homedir
fi
;;
esac
resultPathElements+=( "$path" )
done
local result
printf -v result '%s:' "${resultPathElements[@]}"
printf '%s\n' "${result%:}"
}
...将其用于从文件中安全读取的路径:
printf '%s\n' "$(expandPath "$(<file)")"
或者,一种使用eval
的更简单的方法:
expandPath() {
case $1 in
~[+-]*)
local content content_q
printf -v content_q '%q' "${1:2}"
eval "content=${1:0:2}${content_q}"
printf '%s\n' "$content"
;;
~*)
local content content_q
printf -v content_q '%q' "${1:1}"
eval "content=~${content_q}"
printf '%s\n' "$content"
;;
*)
printf '%s\n' "$1"
;;
esac
}
答案 1 :(得分:2)
使用eval
:
eval cd $(cat file)
否则shell将无法解释~
的含义。
答案 2 :(得分:2)
试试这个:
eval cd `cat ~/cwd`
shell需要扩展'〜'。 eval导致命令通过shell的命令处理运行,包括'〜'扩展。
答案 3 :(得分:1)
无需cat
:
eval cd "$(<~/cwd)"