Get home directory in Linux
You need getuid
to get the user id of the current user and then getpwuid
to get the password entry (which includes the home directory) of that user:
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
struct passwd *pw = getpwuid(getuid());
const char *homedir = pw->pw_dir;
Note: if you need this in a threaded application, you'll want to use getpwuid_r
instead.
How to get $HOME directory of user in bash script root mode?
sudo
runs the script as the root-user
To get the name of the user who initiated sudo you can call echo $SUDO_USER
To get its home directory:
getent passwd $SUDO_USER | cut -d: -f6
How do I find the path to the home directory for Linux?
From the home
crate.
The definition of
home_dir
provided by the standard library is incorrect because it relies on the$HOME
environment variable which has basically no meaning in Windows. This causes surprising situations where a Rust program will behave differently depending on whether it is run under a Unix emulation environment. Neither Cargo nor rustup use the standard libraries definition - instead they use the definition here.
There is discussion about bringing home_dir
back into the standard library, but for now the home
crate is probably your best option. It provides canonical definitions of home_dir
, cargo_home
, and rustup_home
:
match home::home_dir() {
Some(path) => println!("{}", path.display()),
None => println!("Impossible to get your home dir!"),
}
How to get $HOME directory when switching to a different user in bash?
Update: Based on this question's title, people seem to come here just looking for a way to find a different user's home directory, without the need to impersonate that user.
In that case, the simplest solution is to use tilde expansion with the username of interest, combined with eval
(which is needed, because the username must be given as an unquoted literal in order for tilde expansion to work):
eval echo "~$different_user" # prints $different_user's home dir.
Note: The usual caveats regarding the use of eval
apply; in this case, the assumption is that you control the value of $different_user
and know it to be a mere username.
By contrast, the remainder of this answer deals with impersonating a user and performing operations in that user's home directory.
Note:
- Administrators by default and other users if authorized via the
sudoers
file can impersonate other users viasudo
. - The following is based on the default configuration of
sudo
- changing its configuration can make it behave differently - seeman sudoers
.
The basic form of executing a command as another user is:
sudo -H -u someUser someExe [arg1 ...]
# Example:
sudo -H -u root env # print the root user's environment
Note:
- If you neglect to specify
-H
, the impersonating process (the process invoked in the context of the specified user) will report the original user's home directory in$HOME
. - The impersonating process will have the same working directory as the invoking process.
- The impersonating process performs no shell expansions on string literals passed as arguments, since no shell is involved in the impersonating process (unless
someExe
happens to be a shell) - expansions by the invoking shell - prior to passing to the impersonating process - can obviously still occur.
Optionally, you can have an impersonating process run as or via a(n impersonating) shell, by prefixing someExe
either with -i
or -s
- not specifying someExe ...
creates an interactive shell:
-i
creates a login shell forsomeUser
, which implies the following:someUser
's user-specific shell profile, if defined, is loaded.$HOME
points tosomeUser
's home directory, so there's no need for-H
(though you may still specify it)- The working directory for the impersonating shell is the
someUser
's home directory.
-s
creates a non-login shell:- no shell profile is loaded (though initialization files for interactive nonlogin shells are; e.g.,
~/.bashrc
) - Unless you also specify
-H
, the impersonating process will report the original user's home directory in$HOME
. - The impersonating shell will have the same working directory as the invoking process.
- no shell profile is loaded (though initialization files for interactive nonlogin shells are; e.g.,
Using a shell means that string arguments passed on the command line MAY be subject to shell expansions - see platform-specific differences below - by the impersonating shell (possibly after initial expansion by the invoking shell); compare the following two commands (which use single quotes to prevent premature expansion by the invoking shell):
# Run root's shell profile, change to root's home dir.
sudo -u root -i eval 'echo $SHELL - $USER - $HOME - $PWD'
# Don't run root's shell profile, use current working dir.
# Note the required -H to define $HOME as root`s home dir.
sudo -u root -H -s eval 'echo $SHELL - $USER - $HOME - $PWD'
What shell is invoked is determined by "the SHELL environment variable if it is set or the shell as specified in passwd(5)" (according to man sudo
). Note that with -s
it is the invoking user's environment that matters, whereas with -i
it is the impersonated user's.
Note that there are platform differences regarding shell-related behavior (with -i
or -s
):
sudo
on Linux apparently only accepts an executable or builtin name as the first argument following-s
/-i
, whereas OSX allows passing an entire shell command line; e.g., OSX acceptssudo -u root -s 'echo $SHELL - $USER - $HOME - $PWD'
directly (no need foreval
), whereas Linux doesn't (as ofsudo 1.8.95p
).Older versions of
sudo
on Linux do NOT apply shell expansions to arguments passed to a shell; for instance, withsudo 1.8.3p1
(e.g., Ubuntu 12.04),sudo -u root -H -s echo '$HOME'
simply echoes the string literal "$HOME" instead of expanding the variable reference in the context of the root user. As of at leastsudo 1.8.9p5
(e.g., Ubuntu 14.04) this has been fixed. Therefore, to ensure expansion on Linux even with oldersudo
versions, pass the the entire command as a single argument toeval
; e.g.:sudo -u root -H -s eval 'echo $HOME'
. (Although not necessary on OSX, this will work there, too.)The
root
user's$SHELL
variable contains/bin/sh
on OSX 10.9, whereas it is/bin/bash
on Ubuntu 12.04.
Whether the impersonating process involves a shell or not, its environment will have the following variables set, reflecting the invoking user and command: SUDO_COMMAND
, SUDO_USER
, SUDO_UID=
, SUDO_GID
.
See man sudo
and man sudoers
for many more subtleties.
Tip of the hat to @DavidW and @Andrew for inspiration.
How to find a user's home directory on linux or unix?
For UNIX-Like systems you might want to execute "echo ~username
" using the shell (so use Runtime.exec()
to run {"/bin/sh", "-c", "echo ~username"}
).
Getting home directory?
In PowerShell, the most robust way to refer to the current user's home directory is to use automatic variable $HOME
, inside "..."
if it is part of a larger path:
$mySourceDir = "$HOME/Projects/svn/myProject/trunk"; Set-Location $mySourceDir
(Set-Location
is PowerShell'scd
equivalent; thanks to a built-in alias definition, you can usecd
too, however.)If you're passing a path as an argument to a command, you may be able to get away without the enclosing
"..."
, depending on what characters the path contains; e.g.,Set-Location $HOME/Desktop
Works on both Windows and Unix platforms, whereas if you tried to use environment variables such as
$env:HOME
, platform differences would surface.To learn about all automatic variables (built-in variables) that PowerShell defines, see the conceptual
about_Automatic_Variables
help topic (as of this writing, the description of$HOME
reflects just the Windows perspective, but$HOME
does work analogously on Unix platforms).
Use ~
only if you're certain that the current location is a filesystem location:
The current location is PowerShell's generalized concept of the current directory: PowerShell generalizes the concept of a drive to include other (typically) hierarchical data stores, such as the Windows registry, a directory of all defined functions (drive
Function:
), variables (Variable
), or environment variables (Env:
).Each such drive is provided by a drive provider, of which the filesystem [drive provider] is just one instance.
~
is a drive-provider-specific concept, so using just~
, without an explicit reference to a drive provider, refers to the home location as defined by the provider underlying the current location.- Some providers provide no default for what
~
represents, causing attempts to use it to fail; for instance, that is the case for theEnvironment
drive provider and itsEnv:
drive:Set-Location Env:; Set-Location ~
results in errorHome location for this provider is not set. To set the home location, call "(get-psprovider 'Environment').Home = 'path'
- Some providers provide no default for what
It is the drive provider that interprets
~
, so~
also works inside'...'
and"..."
- From a filesystem location, the following commands all work the same:
Set-Location ~/Desktop
Set-Location "~/Desktop"
Set-Location '~/Desktop'
- Contrast this with POSIX-like shells such as
bash
, where it is the shell that expands~
, up front, before the target command sees it, but only if it is unquoted.
- From a filesystem location, the following commands all work the same:
Find home directory in Python?
To get the homedir in python, you can use os.path.expanduser('~')
.
This also works if it's part of a longer path, such as os.path.expanduser('~/some/directory/file.txt')
. If there is no ~ in the path, the function will return the path unchanged.
So depending on what you want to do it's better than reading os.environ['HOME']
The username is available through getpass.getuser()
How to find user's home directory on Windows and Linux in PHP
After not working on this for a long time, I finally decided to definitely answer this question.
There are some usefull environment variables defined on Windows: USERPROFILE
, APPDATA
, LOCALAPPDATA
. They are easily accessible via getenv() function:
getenv('USERPROFILE');
USERPROFILE
exists on any Windows, according to https://learn.microsoft.com/fr-fr/windows/desktop/shell/knownfolderid
So, on Windows, it seems to be reliable.
If you need to store data for the current user, APPDATA
and LOCALAPPDATA
are good variables to find that place.
I've written a package to make these tools reusable: https://github.com/Arcesilas/Platform
It's still work in progress and certainly needs to be improved. Any help is welcome to make this tool reliable on any platform.
Thanks to eryksun whose comments helped a lot in solving this question.
Related Topics
Default Class Inheritance Access
Non-Class Rvalues Always Have Cv-Unqualified Types
What Kinds of Optimizations Does 'Volatile' Prevent in C++
Why Are Strings in C++ Usually Terminated with '\0'
Building and Accessing a List of Types at Compile Time
Why Does the Library Linker Flag Sometimes Have to Go at the End Using Gcc
How to Expand Call to Variadic Template Base Classes
How to Check Whether Two Matrices Are Identical in Opencv
How to Call MAChine Code Stored in Char Array
Does the Gotw #101 "Solution" Actually Solve Anything
What Is the Proper Use of the Comma Operator
Bjarne Stroustrup Says We Must Avoid Linked Lists
Template Within Template: Why "'>>' Should Be '> >' Within a Nested Template Argument List"
Tell Cin to Stop Reading at Newline
Why Cannot a Non-Member Function Be Used for Overloading the Assignment Operator