I want to obtain home dir of any user with echo
echo ~puchuu
>> /home/puchuu
But I cant use variable
echo ~$USER
>> ~puchuu
echo `echo ~$USER`
>> ~puchuu
I want to obtain home dir of any user with echo
echo ~puchuu
>> /home/puchuu
But I cant use variable
echo ~$USER
>> ~puchuu
echo `echo ~$USER`
>> ~puchuu
echo ~$username it's okay, but in sh eval is needed if is a variable
– Felipe Buccioni
Nov 25 '15 at 14:23
eval echo "~$USER" you are making the assumption that $USER does not contain special characters that the shell may interpret. For example, if USER="foo\$bar", then when we eval the shell will substitute $bar into your output which is not what you want. Basically, if you take this route, you need to make sure that $USER is sane input. Most of the time it probably will be, but you should bear this in mind.
– Zorawar
Mar 30 '17 at 01:51
userdir=$(eval echo ~$SOMEUSER)
– Be Kind To New Users
Dec 07 '17 at 03:00
$( getent passwd "john-smith" | cut -d: -f6 )
docker run -it --rm ubuntu bash and then ran user=foobar; yes $'\n' | adduser --home /first $user; deluser $user; delgroup $user; yes $'\n' | adduser --home /second $user; eval echo ~$user and got /second as the output.
– Bruno Bronosky
Dec 31 '20 at 06:17
docker run -it --rm ubuntu bash and then ran username=news; echo ~$username and got ~news I then ran username=news; eval echo ~$username and got /var/spool/news
– Bruno Bronosky
Dec 31 '20 at 06:19
This might work for you:
homedir=$( getent passwd "$USER" | cut -d: -f6 )
This will also work on users that are not you. For instance,
homedir=$( getent passwd "someotheruser" | cut -d: -f6 )
getenv rather than assuming the location of passwd is even a step further than assuming the location of home is /home/
– Evan Carroll
Dec 01 '16 at 22:19
It seems you are that user -- why not
echo $HOME
?
user=pi
user_home=$(bash -c "cd ~$(printf %q "$user") && pwd")
NOTE: The reason this is safe is because bash (even versions prior to 4.4) has its own printf function that includes:
%q quote the argument in a way that can be reused as shell input
See: help printf
# "ls /" is not dangerous so you can try this on your machine
# But, it could just as easily be "sudo rm -rf /*"
$ user="root; ls /"
$ printf "%q" "$user"
root\;\ ls\ /
This is what you get when you are PROTECTED from code injection
$ user_home=$(bash -c "cd ~$(printf "%q" "$user") && pwd"); echo $user_home
bash: line 0: cd: ~root; ls /: No such file or directory
This is what you get when you ARE NOT PROTECTED from code injection
$ user_home=$(bash -c "cd ~$user && pwd"); echo $user_home
bin boot dev etc home lib lib64 media mnt ono opt proc root run sbin srv sys tmp usr var /root
$ user_home=$(eval "echo ~$user"); echo $user_home
/root bin boot dev etc home lib lib64 media mnt ono opt proc root run sbin srv sys tmp usr var
If you are doing this because you are running something as root then you can use the power of sudo:
user=pi
user_home=$(sudo -u "$user" sh -c 'echo $HOME')
If not, the you can get it from /etc/passwd. There are already lots of examples of using eval and getent, so I'll give another option:
user=pi
user_home=$(awk -v u="$user" -v FS=':' '$1==u {print $6}' /etc/passwd)
I would really only use that one if I had a bash script with lots of other awk oneliners and no uses of cut. While many people like to "code golf" to use the fewest characters to accomplish a task, I favor "tool golf" because using fewer tools gives your script a smaller "compatibility footprint". Also, it's less man pages for your coworker or future-self to have to read to make sense of it.
cd ... && pwd is not needed, a simple echo will suffice. Also, I suggest to improve quoting: ~$(printf '%q' "$user")
– MestreLion
Nov 22 '21 at 06:00
user_home=$(bash -c "echo ~$(printf '%q' "$username")") or user_home=$(bash -c "echo ~$username")? Which one is correct?
– Kyo
Jan 30 '24 at 11:39
$username is an actual user name, but, as explained in the answer, the printf %q version is safer as it protects against code injection if $username comes from untrusted sources
– MestreLion
Feb 01 '24 at 20:19
ZSH users can place the tilde (~) outside the expression. This does not work on Bash:
echo ~`echo $USER`
echo ~$user or echo ~"$user" if you are afraid of usernames containing "funny" characters.
– pihentagy
Jan 22 '21 at 13:11
Once you login, run cd to go to your home directory, then run pwd to print the working directory.
echo $HOME.
– wjandrea
Sep 04 '16 at 22:35
how about using realpath instead of eval:
realpath ~$USER
because eval can execute anything, where as realpath will not.
evalorbash -cwith a variable. I added an answer that works safely for an Linux/Unix/macOS system with bash (even if you are not using bash as your shell, it likely has bash available because bashisms are everywhere). https://superuser.com/a/1613980/3376 – Bruno Bronosky Dec 31 '20 at 06:23