私はファイルを持っています~/cwd
。このファイルの内容は次の 1 行です。
~/tmp
cd
この (~/tmp) ディレクトリにfo が必要です。私はしようとしています:
> cd `cat ~/cwd`
そして得た:
-bash: cd: ~/tmp: No such file or directory
RELATIVE パスが失敗したのはなぜですか? の内容~/cwd
が絶対パスの場合、機能します。
相対パスの問題ではありません。これは、シェル評価モデルがパラメーター展開の前にチルダ展開を行うために発生します。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
}
必要なしcat
:
eval cd "$(<~/cwd)"