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

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

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

ls -l /home

但我在一个脚本中使用它,该脚本将部署在其他人的机器上,也许在那些他们不称之为家的机器上(例如 myHome)。

所以我想将其概括为ls -l ~.但它只是列出我的用户的主目录,而不是所有用户的主目录(基本上我想获取计算机上的用户名列表)。

我该如何概括它?

答案1

许多系统都有一个getent命令来列出或查询文件的内容名称服务数据库如passwd, group, services, protocols...

getent passwd | cut -d: -f6

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

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

getent passwd | cut -d: -f1

(注意,这并不意味着这些用户可以登录系统或者他们的主目录已经创建,而是说他们是系统已知的,他们可以被转换为用户ID)。

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

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

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

这也意味着,如果有多个用户共享相同的 uid,则每个 uid 只能获得一个条目,因此请忽略其他条目。

如果你没有getent,你可以求助于perl

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

for 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 而异)并且一些 shell(包括bash)将无法工作(当用户名存储在变量中时,~$user您需要求助)。eval而且您仍然需要找到一种方法来获取用户名列表。

有些 shell 具有内置支持来获取用户名列表。

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

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

    列出用户及其主目录。

    但只有在zsh交互时才有效

  • tcshfishyash是其他三个可以完成用户名的 shell(例如完成~<Tab>参数时),但它们看起来并不能让您以编程方式获取用户名列表。

答案2

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

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

答案3

简短的回答:

compgen -u

中等答案:既然您正在使用bash,您可以列出所有可能的~使用补全compgen -A user。这是很常见的用法,可以缩写compgen -u。作为 shell 内置程序,compgen没有自己的手册页。相反,请参阅重击(1)获取文档并阅读有关部分可编程完成

更彻底的替代方案

如果您非常关心可移植性,您甚至可能无法依赖其他具有bash.在这种情况下,请执行以下操作:

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

解释 长答案尝试了一切,所以它几乎可以在任何 UNIX 系统上工作,无论它是否使用较新的 /etc/nsswitch.conf (GNU/Linux 和 BSD 都带有getent)、传统的 UNIX passwd 平面文件、MacOS 的 Directory服务 1 ( dscl),甚至是较旧的、以猫为主题的 MacOS X 版本和 NeXTSTEP ( nidump)。

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


脚注 1:我已经没有使用过 MacOS 了,所以如果有人可以帮我确认我的语法是正确的(并且输出不包含任何会造成混乱的冒号cut),那就太好了。谢谢。

脚注 ²:我的建议和我所做的可能会有所不同。就我个人而言,我会更频繁地cut -d: -f1 /etc/passwd在命令行中使用传统的方式。经过几十年的重复,我的手指可以打字,而我的大脑却在做其他事情。

答案4

关于什么ls -l ~/..?这列出了主目录父目录中的所有目录。

相关内容