Get home directory by username
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
You can use eval
:
eval echo ~$USER
But see Andrew's comment and glenn's reply below.
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 )
It seems you are that user -- why not
echo $HOME
?
There is a safe way to do this!
on Linux/BSD/macOS/OSX without sudo or root
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
Compare to how other answers respond to code injection
# "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
on Linux/BSD/macOS/OSX as root
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')
on Linux/BSD (but not modern macOS/OSX) without sudo or root
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.