How to get $HOME directory when switching to a different user in bash?
Categories:
Navigating Home: Getting the $HOME Directory After su
or sudo
Understand how to reliably access the correct home directory in Bash when switching users with su
or sudo
, and avoid common pitfalls.
When working in a Bash environment, especially on multi-user systems, it's common to switch user contexts using commands like su
or sudo
. A frequent challenge arises when trying to determine the 'home' directory of the new user. While the HOME
environment variable usually points to the current user's home directory, its behavior can be nuanced depending on how you switch users and the specific command used. This article explores the reliable methods to get the correct $HOME
directory, regardless of the user switching mechanism.
Understanding su
and sudo
Behavior
The key to understanding how to get the correct home directory lies in how su
and sudo
handle environment variables. By default, su
(without -
or --login
) and sudo
(without -i
or --login
) often preserve much of the original user's environment, including the HOME
variable. This can lead to situations where $HOME
still points to the original user's home directory, even after you've successfully switched to a different user ID.
flowchart TD A[Start as User A] --> B{Switch User?} B -->|Yes, `su userB`| C[Environment Partially Preserved] C --> D{`$HOME` still points to User A's home} B -->|Yes, `su - userB` or `sudo -i userB`| E[Full Login Shell] E --> F{`$HOME` correctly points to User B's home} B -->|No| G[Continue as User A] D --> H[Need explicit command to get User B's home] F --> I[`$HOME` is correct] H --> J[e.g., `eval echo ~userB` or `getent passwd userB | cut -d: -f6`]
Behavior of su
and sudo
on the $HOME
environment variable
Reliable Methods to Get the Target User's Home Directory
To ensure you always get the correct home directory for the target user (the user you've switched to or are about to switch to), you should not solely rely on the $HOME
environment variable if you suspect a partial environment transfer. Here are several robust methods:
su - <username>
or sudo -i <username>
when you intend to fully switch to another user's environment, including their home directory, PATH, and other environment variables. This creates a login shell for the target user.Method 1: Using ~
(Tilde Expansion)
The tilde (~
) character in Bash is a powerful shortcut. When used alone, ~
expands to the current user's home directory. When followed by a username, e.g., ~username
, it expands to that specific user's home directory. This expansion happens before the command is executed and is generally reliable.
# As userA, switch to userB without a full login shell
su userB
# Inside userB's shell (but with userA's HOME variable potentially)
# This will correctly show userB's home directory
echo ~userB
# This will show the current user's home, which might be userA's if not a login shell
echo $HOME
# To get the current user's home reliably, even if $HOME is wrong
echo ~
Using tilde expansion to get a user's home directory
Method 2: Querying /etc/passwd
with getent
The /etc/passwd
file (or its equivalent via NSS, which getent
uses) stores user account information, including their home directory. You can query this file directly to get the home directory for any user on the system. This is the most programmatic and reliable way to get a user's home directory, independent of the current shell's environment.
# Get the home directory for 'userB'
getent passwd userB | cut -d: -f6
# Get the home directory for the current effective user
getent passwd "$(whoami)" | cut -d: -f6
Using getent
and cut
to extract home directory from passwd entry
Method 3: Using sudo -H
or sudo -i
for Commands
If you are running a single command as another user via sudo
, you can use sudo -H
to set the HOME
environment variable to the target user's home directory for that specific command. Alternatively, sudo -i
provides a full login shell, ensuring $HOME
is correctly set.
# Run a command as 'userB' with userB's HOME directory set
sudo -H -u userB bash -c 'echo $HOME'
# Run a command as 'userB' with a full login environment
sudo -i -u userB bash -c 'echo $HOME'
# If you just want to see userB's home without switching
sudo -u userB printenv HOME
# Or more directly, using the tilde expansion within sudo
sudo -u userB bash -c 'echo ~'
Using sudo -H
or sudo -i
to ensure correct HOME for commands
sudo
to execute commands that rely on environment variables. Always test to ensure the environment is what you expect, especially for critical scripts. Using sudo -i
or explicitly setting variables is often safer.