Должны определять все домашние каталоги пользователей - проблема с тильдой скриптов

Предположим, что у someuser есть домашний каталог /home/someuser

NAME = someuser

В bash - какое выражение я использую, комбинируя тильду (~) и $NAME, чтобы вернуть домашний каталог пользователей?

HOMEDIRECTORY=~someuser
echo $HOMEDIRECTORY
/home/someuser
NAME=someuser
echo ~$NAME
~someuser

любые предложения?

Ответ 1

Безопаснее:

eval HOMEDIRECTORY="$(printf "~%q" "$NAME")"

Здесь опция %q для printf цитирует и ускользает от опасных символов.

Если $NAME - joe, вы получите что-то вроде /home/joe. Для root вы можете получить /root. Для "abc; rm something" вы получите "~ abc; rm something" вместо того, чтобы что-то удалить.

Ответ 2

Если у вас есть доступ к getent:

getent passwd "$NAME" | cut -d: -f 6

Ответ 3

Tilde (~) это то же самое, что и $HOME, поэтому не все пользователи будут иметь корневой каталог в одном каталоге.

Но если вы настаиваете на использовании тильды, выполните следующие действия:

echo ~/../$NAME

Смотрите:

$ pwd
/home/oreyes
$ export NAME=john 
$ export DIRECTORYNAME=~/../$NAME
$ cd $DIRECTORYNAME
$ pwd
/home/john

Ответ 4

Интересная разница между bash и csh, где ~ $VARNAME фактически делает то, что вы ожидаете!

Это некрасиво, но, похоже, работает в bash:

homedir=`eval "echo ~$USERNAME"`

Теперь $homedir содержит домашний каталог, связанный с $USERNAME.

Ответ 5

ЛУЧШИЙ МЕТОД

Обязательно: ничего (n.b., это тот же метод, что и getent, не требуя getent)

home() { # returns empty string on invalid user
    grep "^$1:" /etc/passwd | cut -d ':' -f 6
}

# grep "^$user:" /etc/passwd | cut -d ':' -f 6
/var/lib/memcached

ЛУЧШИЙ МЕТОД ДЛЯ ЛОТОКА ROOT

Требуется: Linux, root (или sudo)

home() { # returns errorlevel 1 on invalid user
    su "$1" -s '/bin/sh' -c 'echo $HOME'
} 

# su memcached -s '/bin/sh' -c 'echo $HOME'
/var/lib/memcached

РЕШЕНИЕ ДЛЯ ПОЛНОГО РАСШИРЕНИЯ

magic() { # returns unexpanded tilde express on invalid user
    local _safe_path; printf -v _safe_path "%q" "$1"
    eval "ln -sf $_safe_path /tmp/realpath.$$"
    readlink /tmp/realpath.$$
    rm -f /tmp/realpath.$$
}

Пример использования:

$ magic ~nobody/would/look/here
/var/empty/would/look/here

$ magic ~invalid/this/will/not/expand
~invalid/this/will/not/expand

СПОСОБ ЖЕСТКОСТИ CSH

Это BASH script, он просто вызывает csh.

Требуется: csh

home() { # return errorlevel 1 on invalid user
    export user=$1; csh -c "echo ~$user"
}

$ export user=root; csh -c "echo ~$user"
/var/root

$ export user=nodfsv; csh -c "echo ~$user"
Unknown user: nodfsv.

МЕТОД ДЕСУЛЯЦИИ

Обязательный параметр: палец (устаревший)

home() {
    finger -m "$1" | 
    grep "^Directory:" | 
    sed -e 's/^Directory: //' -e 's/ .*//'
}

# finger -m "haldaemon" | 
> grep "^Directory:" | 
> sed -e 's/^Directory: //' -e 's/ .*//'
/home/haldaemon

Вы можете объединить операцию grep в sed, но поскольку этот метод является сочным, я бы не стал беспокоиться.

Ответ 6

один альтернативный путь

awk -F":" '{print "user: "$1", Home directory is: "$6}' /etc/passwd