Quiero enumerar todos los directorios de usuarios en la máquina. Por lo general, haré:
ls -l /home
Pero lo uso en un script que se implementará en otras máquinas y tal vez en esas máquinas no lo llaman hogar (por ejemplo, myHome). Entonces quiero generalizarlo ls -l ~
. Pero solo enumera los directorios de inicio de mis usuarios en lugar del nombre de todos los directorios de inicio de los usuarios (básicamente quiero obtener una lista de los nombres de usuarios en la máquina). ¿Cómo puedo generalizarlo?
bash
shell-script
eval
lakerda
fuente
fuente
~
generalmente es el equivalente de/home/user
, no de/home
o/home/*
(que parecen estar más cerca de su intención).nobody
) tienen su directorio de inicio configurado en/nonexistent
, que, obviamente, no existe. (Por supuesto, esos usuarios también tienen su hash de contraseña establecido en*
y su shell establecido en/usr/sbin/nologin
o/bin/false
, por lo que realmente no pueden iniciar sesión en el sentido normal para empezar).Respuestas:
Muchos sistemas tienen un
getent
comando a la lista o consultar el contenido de los Servicio de nombres de bases de datos comopasswd
,group
,services
,protocols
...Sería una lista de los directorios de inicio (la 6 ª campo delimitado por dos puntos) de todos los usuarios de bases de datos que pueden ser enumerados .
El nombre de usuario en sí está en el primer campo, por lo que para la lista de nombres de usuario:
(tenga en cuenta que no significa que esos usuarios puedan iniciar sesión en el sistema o que se haya creado su directorio de inicio, pero que el sistema los conoce, pueden traducirse a una identificación de usuario).
Para las bases de datos que no se pueden enumerar, puede intentar consultar cada ID de usuario posible individualmente:
(aquí suponiendo que los uids se detengan en 65535 (algunos sistemas admiten más) y un shell que admite la
{x..y}
forma de expansión de llaves de zsh ). Pero no querrá hacer eso a menudo en sistemas donde la base de datos de usuarios está en red (y hay un almacenamiento en caché local limitado) como LDAP, NIS +, SQL ... ya que eso podría implicar mucho tráfico de red (y cargar en el servidor de directorio) ) para hacer todas esas consultas.Eso también significa que si hay varios usuarios que comparten el mismo uid, solo obtendrás una entrada para cada uid, así que echa de menos los demás.
Si no tiene
getent
, puede recurrir aperl
:para
getent passwd
($e[0]
para los nombres de usuario) o:para
getent passwd {0..65535}
con las mismas advertencias.En shells, puede usar
~user
para obtener el directorio de inicio deuser
, pero en la mayoría de los shells, eso solo funciona para un conjunto limitado de nombres de usuario (la lista de caracteres permitidos en los nombres de usuario admitidos para ese~
operador de expansión varía de un shell a otro) y con varias conchas (incluidasbash
),~$user
no funcionarán (necesitaría recurrireval
cuando el nombre del usuario se almacena en una variable allí). Y aún tendría que encontrar una manera de obtener la lista de nombres de usuario.Algunos shells tienen soporte incorporado para obtener esa lista de nombres de usuario.
bash
:compgen -u
devolvería la lista de usuarios en bases de datos que se pueden enumerar.zsh
: la$userdirs
matriz asociativa asigna los nombres de usuario a su directorio de inicio (también limitado a las bases de datos que se pueden enumerar, pero si realiza una~user
expansión para un usuario que se encuentra en una base de datos no enumerable, se agregará una entrada$userdirs
). Entonces puedes hacer:para enumerar usuarios con su directorio de inicio.
Sin
zsh
embargo, eso solo funciona cuando es interactivo .tcsh
,fish
yyash
son otros tres shells que pueden completar nombres de usuario (por ejemplo, al completar~<Tab>
argumentos), pero no parece que le permitan obtener esa lista de nombres de usuario mediante programación.fuente
getent
va a estar allí, lo que supongo que en cierta medida depende del alcance de sus 'otras máquinas'.perl
alternativa.perl -le 'while (@e = getpwent) {print $e[7]}'
funciona bien en macOS.getent passwd
le muestra la base de datos del usuario. El primer campo es el nombre de usuario, el sexto campo es el directorio de inicio de los usuarios.Una mejor manera de enumerar los directorios de inicio de los usuarios es analizarlos
/etc/passwd
y extraerlos desde allí, y no hacer suposiciones sobre dónde pueden estar.Y a juzgar por su segundo comentario, realmente desea los nombres de usuario, no sus directorios de inicio, en cuyo caso,
/etc/passwd
es una mejor opción de todos modos. Tenga en cuenta que algunas máquinas Linux / UNIX tendrán otros mecanismos de autenticación de usuario configurados (por ejemplo, LDAP), por lo que, en última instancia, su consulta es más compleja de lo que podría imaginarse, pero/etc/passwd
es un buen lugar para comenzar.fuente
getent
sistemas que lo admiten.getent
siempre es mejor que el análisis/etc/passwd
(aborda la preocupación con "otros mecanismos de autenticación de usuario").getent
solución es que supone que la fuente de datos se puede enumerar, y no solo consultar por un valor específico. Eso se detalla en la respuesta de Stéphane Chazelas a esta pregunta , pero pensé que agregaría un comentario para cualquiera que lea esta página.La respuesta corta :
La respuesta media : ya que está usando
bash
, puede enumerar todas las terminaciones posibles para~
usarcompgen -A user
. Ese es un uso tan común que se puede abreviarcompgen -u
. Como shell integrado,compgen
no tiene su propia página de manual. En su lugar, consulte bash (1) para obtener documentación y lea la sección sobre Finalización programable .Una alternativa más completa
Si está extremadamente preocupado por la portabilidad, es posible que ni siquiera pueda confiar en otras máquinas
bash
. En ese caso, haz esto:Explicación La respuesta larga lo intenta todo, por lo que funcionará en casi cualquier sistema UNIX, independientemente de si utiliza el /etc/nsswitch.conf más reciente (tanto GNU / Linux como BSD vienen
getent
), el archivo plano tradicional UNIX passwd, MacOS Directory Services¹ (dscl
), o incluso las versiones anteriores de MacOS X con temas de gato y NeXTSTEP (nidump
).Simplicidad Pero, ¿qué tan portátil necesitas? Unix tiene muchas formas de hacer las cosas y algunas veces es más simple. Si tiene que elegir uno, lo recomendaría
getent passwd | cut -d: -f6
para los scripts de shell .²Nota: No he usado MacOS en un tiempo, así que si alguien puede confirmar por mí que tengo la sintaxis correcta (y la salida no incluye ningún punto perdido que pueda estropear
cut
), sería genial. Gracias.Nota al pie ²: Lo que recomiendo y lo que hago puede diferir. Personalmente, usaré más a menudo el tradicional
cut -d: -f1 /etc/passwd
en la línea de comando. Después de décadas de repetición, mis dedos pueden escribirlo mientras mi mente está trabajando en otras cosas.fuente
bash
ha tenidocompgen -u
desde 2.04 lanzado en 2000.¿Qué hay de
ls -l ~/..
? Esto enumera todos los directorios en el padre de su directorio de inicio.fuente
/home
es común en los sistemas Linux, pero ¿qué sucede cuando ejecuta eso comoroot
?). Listado de directorios de inicio es una aventura llena de trampas si desea manejar todos los casos que probablemente encuentre, vea las otras respuestas para más detalles.