Como posso listar todos os nomes de usuários e / ou diretórios home?

16

Eu quero listar todos os usuários dirs na máquina.Normalmente, eu vou fazer:

ls -l /home

Mas eu uso em um script que será implantado em outras máquinas e talvez nas máquinas que eles não chamam de home (por exemplo, myHome). Então, quero generalizá-lo para ls -l ~ . Mas apenas lista meus usuários home dirs em vez de todos os usuários home dirs nome (basicamente eu quero obter uma lista de nomes de usuários na máquina). Como posso generalizar isso?

    
por lakerda 07.12.2017 / 08:50

4 respostas

44

Muitos sistemas têm um comando getent para listar ou consultar o conteúdo dos bancos de dados Name Service como passwd , group , services , protocols ...

getent passwd | cut -d: -f6

Relacionaria os diretórios pessoais (o campo delimitado por dois pontos) de todos os usuários nos bancos de dados que podem ser enumerados .

O próprio nome do usuário está no primeiro campo, portanto, para a lista de nomes de usuários:

getent passwd | cut -d: -f1

(note que isso não significa que os usuários podem efetuar login no sistema ou que seu diretório pessoal tenha sido criado, mas que eles são conhecidos pelo sistema, eles podem ser traduzidos para um ID de usuário).

Para bancos de dados que não podem ser enumerados, você pode tentar consultar cada ID de usuário individualmente:

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

(aqui assumindo que os uids param em 65535 (alguns sistemas suportam mais) e um shell que suporta a forma% c_de% do zsh da expansão de chaves). Mas você não gostaria de fazer isso frequentemente em sistemas onde o banco de dados do usuário está em rede (e há um cache local limitado) como LDAP, NIS +, SQL ... já que isso poderia implicar muito tráfego de rede (e carregar no servidor de diretório ) para fazer todas essas perguntas.

Isso também significa que, se houver vários usuários compartilhando o mesmo uid, você receberá apenas uma entrada para cada uid, então perca os outros.

Se você não tiver {x..y} , poderá recorrer a getent :

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

para perl ( getent passwd para os nomes de usuários) ou:

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

para $e[0] com as mesmas advertências.

Em shells, você pode usar getent passwd {0..65535} para obter o diretório home de ~user , mas na maioria dos shells, isso só funciona para um conjunto limitado de nomes de usuários (a lista de caracteres permitidos em nomes de usuários suportados para esse% o operador de expansãouser varia de shell para shell) e com vários shells (incluindo ~ ), bash não funcionará (você precisaria recorrer a ~$user quando o nome do usuário é armazenado em uma variável lá). E você ainda teria que encontrar uma maneira de obter a lista de nomes de usuários.

Alguns shells têm suporte embutido para obter essa lista de nomes de usuários.

  • eval : bash retornaria a lista de usuários nos bancos de dados que podem ser enumerados.
  • compgen -u : o array associativo zsh mapeia os nomes de usuário para seu diretório pessoal (também limitado a bancos de dados que podem ser enumerados, mas se você fizer uma expansão $userdirs para um usuário que não esteja em um banco de dados enumerável) , uma entrada será adicionada ao ~user ). Então você pode fazer:

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

    para listar usuários com seu diretório inicial.

    Isso só funciona quando o $userdirs é interativo .

  • zsh , tcsh e fish são três outros shells que podem completar nomes de usuários (por exemplo, ao completar yash arguments), mas não parece que eles permitem que você obtenha essa lista de nomes de usuários de forma programática.

por 07.12.2017 / 09:34
17

A melhor maneira de listar os diretórios home dos usuários é analisar /etc/passwd e extraí-los de lá, sem fazer nenhuma suposição sobre onde eles podem estar.

E, a julgar pelo seu segundo comentário, você realmente quer os nomes de usuários, não seus diretórios pessoais. Nesse caso, /etc/passwd é a melhor escolha. Observe que algumas máquinas Linux / UNIX terão outros mecanismos de autenticação de usuário configurados (por exemplo, LDAP) e, por fim, sua consulta é mais complexa do que você imagina, mas /etc/passwd é um bom lugar para começar.

    
por 07.12.2017 / 09:03
6

A resposta curta :

compgen -u

A resposta média : Como você está usando bash , é possível listar todas as conclusões possíveis para ~ usando compgen -A user . Esse é um uso tão comum que pode ser abreviado compgen -u . Como um shell interno, compgen não possui sua própria página man. Em vez disso, consulte bash (1) para documentação e leia a seção sobre Complementação Programável .

Uma alternativa mais completa

Se você estiver extremamente preocupado com a portabilidade, talvez não seja possível confiar em outras máquinas com bash . Nesse caso, faça isso:

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

Explicação A resposta longa tenta tudo, então ele funcionará em praticamente qualquer sistema UNIX, independentemente de ele usar o mais novo /etc/nsswitch.conf (ambos GNU / Linux e BSD vêm com getent ), o tradicional arquivo simples UNIX passwd , Os Serviços de Diretório do MacOS¹ ( dscl ), ou até mesmo os lançamentos antigos do MacOS X com tema de gato e o NeXTSTEP ( nidump ).

Simplicidade Mas, quão portátil você precisa? O Unix tem muitas maneiras de fazer as coisas e, às vezes, é mais simples. Se você tiver que escolher um, eu recomendaria getent passwd | cut -d: -f6 para scripts de shell.²

Nota de rodapé ¹: Eu não usei o MacOS um pouco, então se alguém puder confirmar para mim que eu acertei a sintaxe corretamente (e a saída não inclui nenhum cólon perdido que iria bagunçar cut ), seria ótimo. Obrigado.

Nota de rodapé ²: O que eu recomendo e o que faço pode ser diferente. Pessoalmente, usarei com mais frequência o tradicional cut -d: -f1 /etc/passwd na linha de comando. Depois de décadas de repetição, meus dedos podem digitar enquanto minha mente está trabalhando em outras coisas.

    
por 07.12.2017 / 15:14
2

Que tal ls -l ~/.. ? Isso lista todos os diretórios no pai do seu diretório pessoal.

    
por 07.12.2017 / 13:10