Я хочу перечислить все каталоги пользователей на машине. Обычно я буду делать:
ls -l /home
Но я использую его в сценарии, который будет развернут на других машинах, и, возможно, на тех машинах они не называют его домашним (например, myHome). Поэтому я хочу обобщить это ls -l ~
. Но он просто перечисляет мои домашние каталоги пользователей вместо всех имен домашних каталогов пользователей (в основном я хочу получить список имен пользователей на машине). Как я могу обобщить это?
bash
shell-script
eval
lakerda
источник
источник
~
как правило, это эквивалент/home/user
, а не/home
или/home/*
(что, кажется, ближе к вашему намерению).nobody
домашним каталогам нескольких системных пользователей (в том числе ) было присвоено значение/nonexistent
, которого, очевидно, не существует. (Конечно, у этих пользователей также установлен хэш пароля,*
а оболочка -/usr/sbin/nologin
или/bin/false
, поэтому они действительно не могут войти в обычном смысле для начала.)Ответы:
Многие системы имеют
getent
команду списка или запросить содержание Имя службы баз данных , таких какpasswd
,group
,services
,protocols
...Будет перечислять домашние каталоги (6- е поле с разделителями-двоеточиями) всех пользователей в базах данных, которые могут быть перечислены .
Само имя пользователя находится в первом поле, поэтому для списка имен пользователей:
(обратите внимание, что это не означает, что эти пользователи могут войти в систему или их домашний каталог создан, но что они известны системе, их можно преобразовать в идентификатор пользователя).
Для баз данных, которые не могут быть перечислены, вы можете попробовать и запросить каждый возможный идентификатор пользователя в отдельности:
(здесь предполагается, что uids останавливаются на 65535 (некоторые системы поддерживают больше) и оболочка, которая поддерживает
{x..y}
расширение скобок в zsh ). Но вы не захотите делать это часто в системах, где пользовательская база данных объединена в сеть (и локальное кэширование ограничено), таких как LDAP, NIS +, SQL ... поскольку это может подразумевать большой сетевой трафик (и нагрузку на сервер каталогов). ) сделать все эти запросы.Это также означает, что если несколько пользователей используют один и тот же uid, вы получите только одну запись для каждого uid, поэтому пропустите остальные.
Если у вас нет
getent
, вы можете прибегнуть кperl
:для
getent passwd
($e[0]
для имен пользователей) или:для
getent passwd {0..65535}
тех же предостережений.В оболочках вы можете использовать
~user
для получения домашнего каталогаuser
, но в большинстве оболочек это работает только для ограниченного набора имен пользователей (список разрешенных символов в именах пользователей, поддерживаемых для этого~
оператора расширения, варьируется от оболочки к оболочке) и с несколько оболочек (в том числеbash
)~$user
не будут работать (вам нужно будет прибегнуть к помощи,eval
когда имя пользователя там хранится в переменной). И вам все равно придется найти способ получить список имен пользователей.Некоторые оболочки имеют встроенную поддержку для получения этого списка имен пользователей.
bash
:compgen -u
вернет список пользователей в базах данных, которые могут быть перечислены.zsh
:$userdirs
ассоциативный массив отображает имена пользователей в их домашний каталог (также ограниченный базами данных, которые могут быть перечислены, но если вы выполните~user
расширение для пользователя, который находится в не перечисляемой базе данных, запись будет добавлена$userdirs
). Так что вы можете сделать:перечислить пользователей с их домашним каталогом.
Это работает только когда
zsh
интерактивно, хотя .tcsh
,fish
Иyash
три другие оболочек , которые могут завершить имена пользователей (например , при заполнении~<Tab>
аргументов), но это не похоже , что они позволяют получить этот список имен пользователей программно.источник
getent
будет ли она там, что, я думаю, в какой-то степени зависит от объема их «других машин».perl
альтернативу.perl -le 'while (@e = getpwent) {print $e[7]}'
отлично работает на macOS.getent passwd
показывает базу данных пользователей. Первое поле - это имя пользователя, 6-е поле - домашний каталог пользователей.Лучший способ перечислить домашние каталоги пользователей - это анализировать
/etc/passwd
и извлекать их оттуда, а не делать предположения о том, где они могут быть.И, судя по вашему второму комментарию, вы на самом деле хотите, чтобы имена пользователей, а не их домашние каталоги, в таком случае,
/etc/passwd
в любом случае, являются лучшим выбором. Обратите внимание, что на некоторых машинах Linux / UNIX будут настроены другие механизмы аутентификации пользователей (например, LDAP), и, в конечном счете, ваш запрос является более сложным, чем вы можете себе представить, но/etc/passwd
это хорошее место для начала.источник
getent
о системах, которые его поддерживают.getent
всегда лучше, чем синтаксический анализ/etc/passwd
(он решает проблему с «другими механизмами аутентификации пользователя»).getent
решением состоит в том, что предполагается, что источник данных можно перечислять, а не просто запрашивать конкретное значение. Это подробно описано в ответе Стефана Шазела на этот вопрос , но я хотел бы добавить комментарий для тех, кто просматривает эту страницу.Краткий ответ :
Средний ответ : так как вы используете
bash
, вы можете перечислить все возможные дополнения для~
использованияcompgen -A user
. Это такое общее использование, оно может быть сокращеноcompgen -u
. Как встроенная оболочка,compgen
не имеет своей собственной страницы руководства. Вместо этого смотрите документацию по bash (1) и читайте раздел « Программируемое завершение» .Более тщательная альтернатива
Если вы крайне обеспокоены переносимостью, возможно, вы даже не сможете положиться на другие машины
bash
. В этом случае сделайте это:Пояснение Длинный ответ пробует все, поэтому он будет работать практически на любой системе UNIX, независимо от того, использует ли он более новый файл /etc/nsswitch.conf (вместе с GNU / Linux и BSD
getent
), традиционный плоский файл UNIX passwd, MacOS Службы каталогов¹ (dscl
) или даже более старые версии MacOS X с тематической тематикой cat и NeXTSTEP (nidump
).Простота Но насколько вам нужен портативный компьютер? У Unix есть много способов сделать что-то, а иногда и достаточно простых. Если вам нужно выбрать один, я бы порекомендовал
getent passwd | cut -d: -f6
для сценариев оболочки.Сноска ¹: Я немного не использовал MacOS, поэтому, если кто-то может подтвердить для меня, что я правильно понял синтаксис (и в вывод не включены какие-либо случайные двоеточия, которые могли бы испортиться
cut
), это было бы здорово. Благодарю.Сноска ²: То, что я рекомендую и что я делаю, может отличаться. Лично я чаще буду использовать традиционные
cut -d: -f1 /etc/passwd
в командной строке. После десятилетий повторения мои пальцы могут печатать, пока мой ум работает над другими вещами.источник
bash
было сcompgen -u
тех пор 2,04 выпущен в 2000 годуКак насчет
ls -l ~/..
? В этом списке перечислены все каталоги в родительском каталоге вашего домашнего каталога.источник
/home
это обычное явление в системах Linux, но что происходит, когда вы запускаете это какroot
?). Перечисление домашних каталогов - это приключение, полное ловушек, если вы хотите разобраться во всех случаях, с которыми вы, вероятно, столкнетесь, см. Подробности в других ответах.