Change script directory to user's homedir in a shell script
What about
cd $(getent passwd foo | cut -d: -f6)
and
USER=foo
eval cd ~$USER
works, too (foo is the username)
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 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
Execute script relative to another user's home directory
On Mac OS you don't need to quote. I'm not sure about Linux. However, if
ls ~user
would result in /dir with space/user/ then
sh ~user/rel/path/to/script.sh
would be
sh /dir\ with\ space/user/rel/path/to/script.sh
and this executes if you have set the execution flag on script.sh accordingly.
Create a directory at user's home directory throught a shell script with command mkdir ~/adirectory
The problem was with tilde expansion. Using sh -c $path worked for me.
function init() {
if [ "$PROJECT_DIR" = "" ]; then
export PROJECT_DIR=$HOME/projects
fi
mkdir -p `expand $PROJECT_DIR`
}
function expand(){
echo `sh -c "echo $1"`
}
Temporarily change current working directory in bash to run a command
You can run the cd
and the executable in a subshell by enclosing the command line in a pair of parentheses:
(cd SOME_PATH && exec_some_command)
Demo:
$ pwd
/home/abhijit
$ (cd /tmp && pwd) # directory changed in the subshell
/tmp
$ pwd # parent shell's pwd is still the same
/home/abhijit
Related Topics
How to Remove Warning: Link.Res Contains Output Sections; Did You Forget -T
Why Doesn't Time() from Time.H Have a Syscall to Sys_Time
Automatically Feed Input to Linux Command Line
Ec2 Instance Launched from Ami Not Reachable(Ssh) After Start/Stop or Reboot
Linux Postfix/Dovecot 554 Relay Access Denied
How to Compare Two Text Files for The Same Exact Text Using Bash
Setting Up Sonarqube on Aws Using Ec2
While Using Printf How to Escape Special Characters in Shell Script
How to Check If Linux Console Screensaver Has Blanked Screen
Srlua Makefile Error Lua.H No Such File or Directory
Terminal "Png" Missing When Using Gnuplot
How to Add a Ssh Key to Remote Server
How to Sort Numbers in a Qtreewidget Column
Ffmpeg Concat and Scale Simultaneously
Run Any Linux Terminal Command from Typescript
Different Utf-8 Signature for Same Diacritics (Umlauts) - 2 Binary Ways to Write Umlauts