Try this:
eval cd `cat ~/cwd`
The '~' needs to be expanded by the shell. The eval causes the command to be run through the shell's command processing, which includes '~' expansion.
Question
I have a file, say: ~/cwd
. The content of this file is a single line:
~/tmp
I want fo cd
to this (~/tmp) dir. I'm trying:
> cd `cat ~/cwd`
And got:
-bash: cd: ~/tmp: No such file or directory
Why the RELATIVE paths failed? When the content of the ~/cwd
is absolute path - it works.
La solution 2
Try this:
eval cd `cat ~/cwd`
The '~' needs to be expanded by the shell. The eval causes the command to be run through the shell's command processing, which includes '~' expansion.
Autres conseils
It's not a problem with relative paths -- this happens because the shell evaluation model does tilde expansion BEFORE parameter expansion. Skipping back up to the very beginning of the evaluation process, with eval, introduces security bugs -- so if one REALLY needs to support this (and I argue, strongly, that it's a bad idea), a safe implementation (targeting platforms with the getent
command available) would look like the following:
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%:}"
}
...to use this for a path read from a file safely:
printf '%s\n' "$(expandPath "$(<file)")"
Alternately, a simpler approach that uses eval
carefully:
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
}
Use eval
:
eval cd $(cat file)
Otherwise the shell will not be able to interpret the meaning of ~
.
Without the need of cat
:
eval cd "$(<~/cwd)"