Code:
$ x=~/abc
$ echo "$x"
/home/vaphell/abc
bash sees that naked ~ in the code, right off the bat substitutes it with full home dir before doing anything else with this code. Assignment never sees ~, gets /home/user/abc instead and that's the value stored in $x here.
Code:
$ x="~/abc"
$ echo "$x"
~/abc
this is pretty much equivalent to your scenario. When you prompt user for input, stuff gets saved in the variable verbatim. If you typed in ~, it's going to be literally ~. There is no dir that is literally named '~' so you get errors. That means that you need to process that ~ alias by hand to the true value before trying to access the path.
You can do this with builtin ${x/pattern/replacement} expansion.
pattern obviously is going to be ~ and the replacement is going to be $HOME=/home/username. If the pattern is prefixed with #, it forces the matching only at the start, ~'s in the middle/at the end are going to be ignored.
Code:
$ x="~/abc~"
$ echo "${x/#~/====}"
====/abc~
$ echo "${x/#~/$HOME}"
/home/vaphell/abc~
Note that my in my previous posts i replaced ~/ with $HOME/ because reasons (~user is a valid alias too so ~=$HOME is not always a rock solid assumption) but it won't work if you type ~ alone.
'~' -> $HOME might be just enough for your needs, but you could also write a tidy function that translates stuff and abstracts the gritty details away, eg
Code:
unroll()
{
if [[ $1 = '~' ]] # ~
then
echo "$HOME"
elif [[ $1 = '~'/* ]] # ~/stuff
then
echo "$HOME/${1#*/}"
elif [[ $1 = '~'[[:alnum:]]* ]] # ~user/stuff, looks in /etc/passwd for user's home dir
then
local id=${1#'~'}; id=${id%%/*}
IFS=: read -r _ _ _ _ _ hdir _ < <( grep "^$id:" /etc/passwd )
[[ -n "$hdir" ]] && echo "$hdir/${1#*/}"
else
echo "$1"
fi
}
unrolled_find_dir=$( unroll "$find_dir" )
unrolled_dest_dir=$( unroll "$dest_dir" )
that function in action:
Code:
$ unroll '~/abc~'
/home/vaphell/abc~
$ unroll '~pulse/x/~'
/var/run/pulse/x/~
$ unroll '~root/aaa'
/root/aaa
$ unroll '/usr/bin'
/usr/bin
Bookmarks