должны определить все домашние каталоги пользователей - проблема сценариев тильды - PullRequest
5 голосов
/ 15 января 2010

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

NAME = someuser

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

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

есть предложения?

Ответы [ 6 ]

16 голосов
/ 15 января 2010

Безопаснее :

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

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

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

6 голосов
/ 15 января 2010

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

getent passwd "$NAME" | cut -d: -f 6
1 голос
/ 22 мая 2015

ЛУЧШИЙ МЕТОД

Требуется: ничего ( н.б., это та же техника, что и 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

КРАСИВЫЙ МЕТОД ДЛЯ КОРНЯ LINUX

Обязательно: 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, он просто вызывает 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 , но так как этот метод неудачен, я бы не стал беспокоиться.

1 голос
/ 15 января 2010

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

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

homedir=`eval "echo ~$USERNAME"`

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

1 голос
/ 15 января 2010

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

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

echo ~/../$NAME

См .:

$ pwd
/home/oreyes
$ export NAME=john 
$ export DIRECTORYNAME=~/../$NAME
$ cd $DIRECTORYNAME
$ pwd
/home/john
0 голосов
/ 15 января 2010

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

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