Getting a User’s Home Directory in Bash
The tilde expansion ~username works fine when the username is literal, but fails when the username is stored in a variable like ~$user. Bash doesn’t perform tilde expansion on variables by default—it only expands ~ at the beginning of a word before variable expansion happens.
Using eval
The most common approach is to use eval:
user="alice"
userhome=$(eval echo ~$user)
echo "$userhome" # Output: /home/alice
The eval forces a re-evaluation of the string, allowing the tilde expansion to occur after variable substitution. However, eval has security implications if the variable comes from untrusted input, since it executes arbitrary code.
Using getent (Recommended)
A safer and more portable approach is to query the system’s user database directly with getent:
user="alice"
userhome=$(getent passwd "$user" | cut -d: -f6)
echo "$userhome" # Output: /home/alice
This method:
- Works across Linux, BSD, and macOS
- Handles users from LDAP, NIS, or other directory services (not just
/etc/passwd) - Avoids shell expansion quirks
- Is safer with untrusted input
Checking if the User Exists
getent returns nothing if the user doesn’t exist, so you can validate:
user="alice"
if userhome=$(getent passwd "$user" | cut -d: -f6); then
echo "Home directory: $userhome"
else
echo "User '$user' not found" >&2
exit 1
fi
Using Parameter Expansion with eval
If you prefer eval but want to be more explicit:
user="alice"
userhome=$(eval echo "~${user}")
The quotes ensure the variable is expanded safely. Still use this only with trusted input.
Using HOME Variable as Fallback
For the current user, just reference the $HOME variable directly:
echo "$HOME" # Current user's home
For other users, stick with getent.
Performance Consideration
If you’re calling this repeatedly in a loop, getent is slightly faster than eval echo since it’s a single system call rather than spawning a subshell:
# Good for loops
for user in alice bob charlie; do
home=$(getent passwd "$user" | cut -d: -f6)
[[ -n "$home" ]] && echo "$user: $home"
done
Summary
- For safety and portability: Use
getent passwd "$user" | cut -d: -f6 - For the current user only: Use
$HOME - For trusted input only: Use
eval echo ~$userif getent isn’t available
The getent approach is the modern standard across sysadmin practices and handles edge cases like centralized authentication better than tilde expansion.
Practical Tips and Common Gotchas
When working with programming languages on Linux, environment management is crucial. Use version managers like asdf, pyenv, or sdkman to handle multiple language versions without system-wide conflicts. Always pin dependency versions in production to prevent unexpected breakage from upstream changes.
For build automation, modern alternatives often outperform traditional tools. Consider using just or task instead of Make for simpler task definitions. Use containerized build environments to ensure reproducibility across different development machines.
Debugging Strategies
Start with the simplest debugging approach and escalate as needed. Print statements and logging often reveal the issue faster than attaching a debugger. For complex issues, use language-specific debuggers like gdb for C and C++, jdb for Java, or dlv for Go. Always check error messages carefully before diving into code.
Quick Verification
After applying the changes described above, verify that everything works as expected. Run the relevant commands to confirm the new configuration is active. Check system logs for any errors or warnings that might indicate problems. If something does not work as expected, review the steps carefully and consult the official documentation for your specific version.

This is not the right way to get the home directory in the shell scripts. This would not fail even when there is no user with the given name available. The best way is to either user getent or by using awk to get it from the /etc/passwd file