Bash prefix string with tilde to expand to home directory

4

I can't figure out how to prefix a string (e.g. "user1") with a tilde (~) to produce ~user1 and have that expand to user1's home directory.

Here is what I have now:

USER="user1"
ls ~${USER}
ls: cannot access ~user1: No such file or directory

~user1 is not being expanded. How can I achieve it?

edit

This does not work:

$ cat test.sh
USER="user1"
ls $(~$USER)

$ sh -x test.sh
+ USER=user1
+ ~user1
test.sh: 1: ~user1: not found
+ ls
test.sh

bernie

Posted 2012-09-14T15:29:18.750

Reputation: 260

Using /home/user1 is not an option? – terdon – 2012-09-14T15:34:46.560

Don't use USER it is your name. Instead use lower case variables. – ctrl-alt-delor – 2012-09-14T15:43:21.703

why should lower case be preferred? – bernie – 2012-09-14T15:47:09.407

3so you don't overwrite the built in variables such as USER. USER holds the name of the current user that is executing the command. – ctrl-alt-delor – 2012-09-14T15:52:43.223

ok so USER in particular is problematic, not all uppercase var names are. Thanks – bernie – 2012-09-14T15:53:35.627

1yes but do you want to learn them all, and then keep up to date with all new ones. For this reason it is customary to have all local variables in shell scripts as lower-case. – ctrl-alt-delor – 2012-09-14T16:03:01.173

Answers

6

If your user's directory is not simply /home/user, you can use eval in your script (source):

USER_HOME=$(eval echo ~${USER})
echo ${USER_HOME}

terdon

Posted 2012-09-14T15:29:18.750

Reputation: 45 216

This works. Now, should I prefer eval or bash -c? – bernie – 2012-09-14T15:51:59.870

On second thought, I think that bash -c will start a new bash process so it will be marginally slower/more resource intensive. – terdon – 2012-09-14T15:58:08.537

While researching this, I found this link which explains what is happening and why eval is necessary: http://fvue.nl/wiki/Bash:_Why_use_eval_with_variable_expansion%3F

– bernie – 2012-09-14T15:59:02.220

3

This is a general way to get bash to re-evaluate, but the use of eval may be better as it will not spawn a new process. (echo is built into bash so not a new process)

user="user1"
bash -c "ls ~${user}"

ctrl-alt-delor

Posted 2012-09-14T15:29:18.750

Reputation: 1 886

2nd way does not work. see my edit – bernie – 2012-09-14T15:49:53.883

This works. Now, should I prefer eval or bash -c? – bernie – 2012-09-14T15:52:25.363

eval is probably more portable as it does not care what the shell's name is. – ctrl-alt-delor – 2012-09-14T15:58:26.200