JohnE
JohnE

Reputation: 30444

Expand variable before tilde

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

Answers (2)

glenn jackman
glenn jackman

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

KamilCuk
KamilCuk

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

Related Questions