Inspired by the work Charles Duffy did in this answer and the work of Jonathan Leffler in this one and because I couldn't leave well-enough alone.
I went and wrote expandTilde.sh:
#!/bin/bash
doExpand() {
local path
local -a resultPathElements
for path in "$@"; do
: "$path"
case $path in
"~+")
path=$PWD
;;
"~+"/*)
path=$PWD/${path#"~+/"}
;;
"~-")
path=$OLDPWD
;;
"~-"/*)
path=$OLDPWD/${path#"~-/"}
;;
"~")
path=${HOME-~}
;;
"~"/*)
path=$HOME/${path#"~/"}
;;
"~"[0-9]|"~"[+-][0-9])
local num=${path#"~"}
local op=${num%%[0-9]*}
num=${num#[+-]}
local opath=$path
if [ "$op" = "-" ]; then
((num+=1))
fi
path=${DIRSTACK[@]: $op$num:1}
: "${path:=$opath}"
;;
"~"*)
local username=${path%%/*}
username=${username#"~"}
IFS=: read -r _ _ _ _ _ homedir _ < <(getent passwd "$username")
if [ "$homedir" ]; then
if [[ $path = */* ]]; then
path=${homedir}/${path#*/}
else
path=$homedir
fi
fi
;;
esac
resultPathElements+=( "$path" )
done
local result
printf -v result '%s:' "${resultPathElements[@]}"
printf '%s\n' "${result%:}"
}
expandAssign() {
local -a pathElements
IFS=: read -r -a pathElements <<<"$1"
: "${pathElements[@]}"
doExpand "${pathElements[@]}"
}
expandString() {
doExpand "$1"
}
So two questions:
Did I miss any cases or get any cases wrong? (Tests in the github repo.)
Can this be improved in any meaningful ways?