如何列出所有用户名和/或主目录?


16

我要列出计算机上的所有用户目录。通常,我会这样做:

ls -l /home

但是我在一个脚本中使用它,该脚本将部署在其他计算机上,也许会在他们不称其为Home的计算机上(例如myHome)。所以我想将其概括为ls -l ~。但这只是列出我的用户家庭目录,而不是列出所有用户家庭目录名称(基本上,我想在计算机上获取用户名称的列表)。我该如何概括呢?


19
实际上,不能保证所有用户的主目录都是任何一个目录的子目录。
hobbs

17
@hobbs或它们甚至一直存在到用户登录为止。这是那些看似简单的问题之一,很快就会变得复杂。
AugustBitTony

11
请记住,这~通常等效于/home/user,不是/home/home/*(看起来更接近您的意图)。
伊桑·卡明斯基

2
@EightBitTony:...也不保证主目录根本存在。例如,在我的Ubuntu安装中,几个系统用户(包括nobody)将其主目录设置为/nonexistent,这显然不存在。(当然,这些用户的密码哈希也设置为*,shell设置为/usr/sbin/nologin/bin/false,所以从一开始他们就无法正常登录。)
Ilmari Karonen

1
另一方面,(旧式的)NFS服务器可能会为其操作系统不知道名称的用户提供主目录。
rackandboneman

Answers:


45

许多系统有一个getent对list命令或查询的内容名称服务数据库一样passwdgroupservicesprotocols...

getent passwd | cut -d: -f6

将列出可以枚举的数据库中所有用户的主目录(第6 冒号分隔的字段)。

用户名本身在第一个字段中,因此对于用户名列表:

getent passwd | cut -d: -f1

(请注意,这并不意味着那些用户可以登录系统或已经创建了其主目录,但是它们对于系统是已知的,可以转换为用户标识)。

对于无法枚举的数据库,您可以尝试分别查询每个可能的用户ID:

getent passwd {0..65535} | cut -d: -f1,6

(这里假设uid在65535处停止(某些系统支持更多)和一个支持zsh {x..y}形式的大括号扩展的shell )。但是您不希望在用户数据库联网(并且本地缓存有限)的系统上经常这样做,例如LDAP,NIS +,SQL ...,因为这可能意味着大量的网络流量(并在目录服务器上加载) )进行所有这些查询。

这也意味着,如果有多个用户共享同一个uid,则每个uid只会获得一个条目,因此会错过其他条目。

如果没有getent,您可以诉诸perl

perl -le 'while (@e = getpwent) {print $e[7]}'

用于getent passwd$e[0]用于用户名),或:

perl -le 'for ($i=0;$i<65536;++$i) {
  if (@e = getpwuid $i) {print $e[0] ": " $e[7]}}'

对于getent passwd {0..65535}相同的警告。

在shell中,您可以~user用来获取的主目录user,但在大多数shell中,该目录仅适用于有限的用户名集(该~扩展操作符支持的用户名中允许的字符列表随shell的不同而不同)以及几个外壳程序(包括bash~$user将不起作用(eval当用户名存储在变量中时,您需要诉诸于此)。而且,您仍然必须找到一种获取用户名列表的方法。

一些外壳程序具有内置支持来获取用户名列表。

  • bashcompgen -u将返回可以枚举的数据库中的用户列表。
  • zsh$userdirs关联数组将用户名映射到其主目录(也限于可以枚举的数据库,但是如果您对~user不可枚举数据库中的用户进行扩展,则会将一个条目添加到$userdirs)。因此,您可以执行以下操作:

    printf '%s => %s\n' "${(kv@)userdirs}"

    列出用户及其主目录。

    但这仅在zsh交互式时有效

  • tcshfish还有yash另外三个可以完成用户名的shell(例如,在完成~<Tab>参数时),但是看起来它们不能让您以编程方式获取该用户名列表。


OP所面临的挑战将是知道是否getent会存在,这在某种程度上取决于他们“其他机器”的范围。
AugustBitTony

1
@EightBitTony,我添加了一个perl替代方法。
斯特凡Chazelas

1
在Mac上,可能涉及到Open Directory。
SilverWolf-恢复莫妮卡

@seaturtle,perl -le 'while (@e = getpwent) {print $e[7]}'在macOS上工作正常。
斯特凡Chazelas

1
@FloHe,这些是用户名。Unix系统上的大多数用户是特殊的系统用户,他们的生命专用于运行系统服务。getent passwd显示您的用户数据库。第一个字段是用户名,第六个字段是用户的主目录。
斯特凡Chazelas

17

列出用户主目录的一种更好的方法是/etc/passwd从那里解析并提取它们,而不对它们可能位于的位置做任何假设。

从第二条评论来看,您实际上希望的是用户名,而不是其主目录,无论如何,这/etc/passwd是一个更好的选择。请注意,某些Linux / UNIX计算机将配置其他用户身份验证机制(例如LDAP),因此最终,您的查询比您最初想象的要复杂,但是/etc/passwd是一个很好的起点。


9
另请参阅getent支持它的系统。
库萨兰达

6
是的,getent总比解析好/etc/passwd(它解决了“其他用户身份验证机制”的问题)。
史蒂芬·基特

@Kusalananda getent解决方案的问题是它假定可以枚举数据源,而不仅仅是查询特定值。StéphaneChazelas对此问题的答案进行了详细说明,但是我想为浏览此页面的任何人添加评论。
安德鲁·亨利

7

简短的答案

compgen -u

介质的答案:由于您使用的bash,你可以列出所有可能的完成为~使用compgen -A user。这种用法很常见,可以缩写compgen -u。作为内置的shell,compgen没有自己的手册页。相反,请参阅bash(1)以获得文档,并阅读有关Programmable Completion的部分。

更彻底的选择

如果您非常担心可移植性,则甚至可能无法依靠其他具有的机器bash。在这种情况下,请执行以下操作:

(getent passwd ||
    dscl . -ls /Users dsAttrTypeNative:homeDirectory || 
    nidump passwd  ||
    cat /etc/passwd) 2>/dev/null  |  cut -d: -f6

解释 长答案将尝试所有内容,因此无论它是否使用较新的/etc/nsswitch.conf(GNU / Linux和BSD都随附getent),传统的UNIX passwd平面文件,MacOS的它,它都几乎可以在任何UNIX系统上工作。目录服务¹(dscl),甚至是较旧的猫主题MacOS X版本和NeXTSTEP(nidump)。

简便性 但是,您需要多便携?Unix有许多做事的方法,有时更简单。如果您必须选择其中之一,我建议您getent passwd | cut -d: -f6使用Shell脚本。²


脚注¹:我没用过MacOS,所以如果有人可以向我确认我的语法正确(并且输出中不包含会弄乱的杂散冒号cut),那就太好了。谢谢。

脚注²:我的建议和所做的可能有所不同。就个人而言,我将cut -d: -f1 /etc/passwd在命令行上更多地使用传统语言。经过数十年的重复,当我的头脑在做其他事情时,我的手指可以打字。


2
随系统一起提供的所有Mac OS X计算机几乎都可以保证具有bash。(和zsh和其他几个shell一样。)
SilverWolf-恢复莫妮卡的时间

的确如此,但是当我使用MacOS时,Apple很久没有更新bash了,这是我必须经常更换的一些棘手的版本3东西。苹果在更新bash方面做得更好吗?
hackerb9


没错,没想到。我的bash版本(macOS Sierra 10.12.6)是3.2.57。(:
SilverWolf-恢复莫妮卡

无论如何,bashcompgen -u自2000年发布,2.04
斯特凡Chazelas

2

ls -l ~/..呢 这列出了主目录的父目录中的所有目录。


4
这仅在所有主目录都位于同一目录中的系统上起作用,该目录并不多(您可能认为/home在Linux系统上很常见,但是当您将其作为root?运行时会发生什么)。如果您想处理所有可能遇到的情况,列出主目录是一个充满陷阱的冒险,请参阅其他答案以获取详细信息。
史蒂芬·基特

7
可以说,这是迄今为止直接回答OP所感知问题的唯一答案。但是,它不能解决OP的潜在问题。
管道

1
该答案的价值在于理解它遗漏了什么,以及为什么它不如其他投票更高的答案那么好。
Criggie's
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.