Reputation: 30444
I'm sure this has been asked before but I can't find anything. We have inscrutable login names on a shared machine and want to use shell variables to substitute the hard-to-remember login names for people's real names.
For example, let's say Omar's login name is xyz123. I can do this:
$ omar=xyz123
$ echo ~$omar
and output looks fine:
~xyz123
but if I type this:
$ ls ~$omar
there is an error:
ls: cannot access ~xyz123: No such file or directory
I think it's because tilde expansion happens before variable expansion but can't figure out how to get around this.
Perhaps this answer is related although I'm not sure: How to manually expand a special variable (ex: ~ tilde) in bash
Upvotes: 3
Views: 230
Reputation: 247210
bash expands the tilde before the variable. See https://www.gnu.org/software/bash/manual/bash.html#Shell-Expansions
The shell will see if the literal characters $
o
m
a
r
are a login name. As they are not, the tilde is not expanded. The shell eventually sees $omar
as a variable and substitutes that. It then hands the expanded word ~xyz123
to echo
which just prints it.
Similarly, it hands the word ~xyz123
to ls
. Since ls does not do its own tilde expansion, it is looking for a file in your current directory named ~xyz123
with a literal tilde. Since such a file does not exist you get that error.
If you want ls ~$var
to list files, you need eval ls ~$var
. Or, since eval is considered very unsafe to use casually, you could do this instead:
ls "$(getent passwd "$omar" | cut -d: -f6)"
Upvotes: 3
Reputation: 141930
I would go with checking if "$omar"
is a valid user with id
and then using eval
to force double expansion. So protect against evil eval
and then do it.
if ! id "$omar" >/dev/null 2>&1;
echo "Error: user with the name $omar does not exist!" >&2
exit 1
fi
eval echo "\"~$omar\""
Upvotes: 0