Quero listar todos os diretórios de usuários na máquina. Geralmente, farei:
ls -l /home
Mas eu o uso em um script que será implantado em outras máquinas e talvez nas máquinas que eles não chamam de lar (por exemplo, myHome). Então, eu quero generalizar isso ls -l ~
. Mas apenas lista os diretórios pessoais dos usuários em vez do nome de todos os usuários domésticos (basicamente quero obter uma lista dos nomes dos usuários na máquina). Como posso generalizá-lo?
bash
shell-script
eval
Lakerda
fonte
fonte
~
geralmente é o equivalente de/home/user
, não de/home
ou/home/*
(que parece estar mais próximo de sua intenção).nobody
) têm seu diretório pessoal definido como/nonexistent
, o que, obviamente, não existe. (Claro, os usuários também têm o seu conjunto de hash de senha para*
e seu conjunto de shell para/usr/sbin/nologin
ou/bin/false
, então eles realmente não pode logar-se no sentido normal para começar.)Respostas:
Muitos sistemas têm um
getent
comando à lista ou consultar o conteúdo dos Name Service bases de dados comopasswd
,group
,services
,protocols
...Listaria os diretórios pessoais (o 6 ° campo delimitado por dois pontos) de todos os usuários nos bancos de dados que podem ser enumerados .
O nome do usuário está no primeiro campo, portanto, para a lista de nomes de usuário:
(observe que isso não significa que esses usuários podem efetuar login no sistema ou que seu diretório pessoal foi criado, mas que eles são conhecidos pelo sistema, podem ser traduzidos para um ID do usuário).
Para bancos de dados que não podem ser enumerados, você pode tentar consultar cada ID de usuário possível individualmente:
(assumindo que os uids param em 65535 (alguns sistemas suportam mais) e um shell que suporta a
{x..y}
forma de expansão de chaves do zsh ). Mas você não gostaria de fazer isso frequentemente em sistemas em que o banco de dados do usuário está em rede (e há cache local limitado) como LDAP, NIS +, SQL ... pois isso pode implicar muito tráfego de rede (e carregar no servidor de diretório ) para fazer todas essas consultas.Isso também significa que, se houver vários usuários compartilhando o mesmo uid, você receberá apenas uma entrada para cada uid; portanto, perca os outros.
Se você não possui
getent
, pode recorrer aperl
:para
getent passwd
($e[0]
para os nomes de usuário) ou:para
getent passwd {0..65535}
com as mesmas ressalvas.Nos shells, você pode usar
~user
para obter o diretório inicial deuser
, mas na maioria dos shells, isso funciona apenas para um conjunto limitado de nomes de usuários (a lista de caracteres permitidos nos nomes de usuários suportados pelo~
operador de expansão varia de shell para shell) e com vários shells (inclusivebash
),~$user
não funcionarão (você precisará recorrereval
quando o nome do usuário estiver armazenado em uma variável). E você ainda teria que encontrar uma maneira de obter a lista de nomes de usuário.Alguns shells têm suporte embutido para obter essa lista de nomes de usuários.
bash
:compgen -u
retornaria a lista de usuários em bancos de dados que podem ser enumerados.zsh
: a$userdirs
matriz associativa mapeia os nomes de usuários para o diretório inicial (também limitado aos bancos de dados que podem ser enumerados, mas se você fizer uma~user
expansão para um usuário que esteja em um banco de dados não enumerável, uma entrada será adicionada$userdirs
). Então você pode fazer:para listar usuários com seu diretório inicial.
Isso só funciona quando
zsh
é interativo .tcsh
,fish
eyash
são três outros shells que podem completar nomes de usuário (por exemplo, ao concluir~<Tab>
argumentos), mas não parece que eles permitem obter essa lista de nomes de usuário programaticamente.fonte
getent
ele estará lá, o que eu acho que até certo ponto depende do escopo de suas 'outras máquinas'.perl
alternativa.perl -le 'while (@e = getpwent) {print $e[7]}'
funciona bem no macOS.getent passwd
mostra o banco de dados do usuário. O primeiro campo é o nome do usuário, o sexto campo é o diretório inicial do usuário.Uma maneira melhor de listar os diretórios pessoais dos usuários é analisá
/etc/passwd
-los e extraí-los a partir daí, e não fazer nenhuma suposição sobre onde eles podem estar.E, a julgar pelo seu segundo comentário, você realmente deseja os nomes de usuário, e não os diretórios pessoais, nesse caso,
/etc/passwd
é uma opção melhor de qualquer maneira. Observe que algumas máquinas Linux / UNIX terão outros mecanismos de autenticação de usuário configurados (por exemplo, LDAP) e, portanto, sua consulta é mais complexa do que você imagina, mas/etc/passwd
é um bom ponto de partida.fonte
getent
em sistemas que o suportam.getent
é sempre melhor do que analisar/etc/passwd
(trata da preocupação com "outros mecanismos de autenticação de usuário").getent
solução é que ela pressupõe que a fonte de dados possa ser enumerada e não apenas consultada por um valor específico. Isso está detalhado na resposta de Stéphane Chazelas a esta pergunta , mas eu gostaria de adicionar um comentário para qualquer um que folhear esta página.A resposta curta :
A resposta média : como você está usando
bash
, é possível listar todas as conclusões possíveis para~
usarcompgen -A user
. Esse é um uso tão comum que pode ser abreviadocompgen -u
. Como um shell embutido,compgen
não possui sua própria página de manual. Em vez disso, consulte o bash (1) para obter a documentação e leia a seção Conclusão programável .Uma alternativa mais completa
Se você está extremamente preocupado com a portabilidade, talvez nem consiga confiar em outras máquinas
bash
. Nesse caso, faça o seguinte:Explicação A resposta longa tenta de tudo, por isso funcionará em praticamente qualquer sistema UNIX, independentemente de usar o /etc/nsswitch.conf mais recente (ambos vêm com o GNU / Linux e o BSD
getent
), o tradicional arquivo simples de senha do UNIX, o MacOS Directory Services¹ (dscl
), ou mesmo versões mais antigas do MacOS X com tema de gato e 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ê precisar escolher um, eu recomendaria
getent passwd | cut -d: -f6
para scripts de shell.²Nota de rodapé ¹: eu não uso o MacOS há um tempo, portanto, se alguém puder confirmar para mim que eu tenho a sintaxe correta (e a saída não inclui nenhum cólon perdido que estragaria
cut
), isso seria ótimo. Obrigado.Nota de rodapé²: O que eu recomendo e o que faço pode ser diferente. Pessoalmente, usarei mais frequentemente 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.fonte
bash
tevecompgen -u
desde 2.04 lançado em 2000.Que tal
ls -l ~/..
? Isso lista todos os diretórios no pai do seu diretório pessoal.fonte
/home
é comum nos sistemas Linux, mas o que acontece quando você executa isso comoroot
?). Listar diretórios pessoais é uma aventura cheia de armadilhas, se você quiser lidar com todos os casos que provavelmente encontrará, consulte as outras respostas para obter detalhes.