Come posso elencare tutti i nomi utente e / o le home directory?


16

Voglio elencare tutte le directory degli utenti sulla macchina. Di solito, farò:

ls -l /home

Ma lo uso in uno script che verrà distribuito su altre macchine e forse su quelle macchine che non lo chiamano home (ad esempio myHome). Quindi voglio generalizzarlo ls -l ~. Ma elenca solo le directory home dei miei utenti anziché tutti i nomi delle home directory degli utenti (in pratica voglio ottenere un elenco dei nomi degli utenti sulla macchina). Come posso generalizzarlo?


19
C'è infatti, alcuna garanzia che le home directory di tutti gli utenti sono sottodirectory di qualsiasi una directory.
Hobbs,

17
@hobbs o che esistono persino fino a quando l'utente non accede. Questo è uno di quei problemi apparentemente semplici che diventano complessi molto rapidamente.
EightBitTony il

11
Tieni presente che ~è generalmente l'equivalente di /home/user, non di /homeo /home/*(che sembrano essere più vicini alla tua intenzione).
Ethan Kaminski il

2
@EightBitTony: ... né esiste alcuna garanzia che la directory home esista affatto . Ad esempio, sulla mia installazione di Ubuntu, diversi utenti di sistema (incluso nobody) hanno la loro directory home impostata su /nonexistent, che, ovviamente, non esiste. (Naturalmente, quegli utenti hanno anche la loro password hash impostata su *e la shell impostata su /usr/sbin/nologino /bin/false, quindi non possono davvero accedere nel senso normale per cominciare.)
Ilmari Karonen

1
D'altra parte, un server NFS (vecchia scuola) potrebbe servire home directory per utenti che non sono noti per nome al suo sistema operativo.
Rackandboneman,

Risposte:


45

Molti sistemi hanno un getentcomando per elenco o interrogare il contenuto delle Name Service database come passwd, group, services, protocols...

getent passwd | cut -d: -f6

Sarebbe elencare le home directory (il 6 ° campo delimitato colon) di tutti gli utenti nel database che possono essere enumerati .

Il nome utente stesso si trova nel primo campo, quindi per l'elenco dei nomi utente:

getent passwd | cut -d: -f1

(notare che ciò non significa che quegli utenti possano accedere al sistema o che la loro home directory sia stata creata, ma che sono noti al sistema, possono essere tradotti in un ID utente).

Per i database che non possono essere enumerati, puoi provare e interrogare ogni possibile ID utente singolarmente:

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

(qui supponendo che gli uids si fermino a 65535 (alcuni sistemi supportano di più) e una shell che supporta la {x..y}forma di espansione brace di zsh ). Ma non vorrai farlo spesso su sistemi in cui il database degli utenti è collegato in rete (e la memorizzazione nella cache locale è limitata) come LDAP, NIS +, SQL ... poiché ciò potrebbe implicare molto traffico di rete (e caricare sul server di directory ) per fare tutte quelle domande.

Ciò significa anche che se ci sono più utenti che condividono lo stesso UID, otterrai solo una voce per ciascun UID, quindi perdi gli altri.

Se non lo hai getent, puoi ricorrere a perl:

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

per getent passwd( $e[0]per i nomi utente) o:

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

per getent passwd {0..65535}con gli stessi avvertimenti.

Nelle shell, è possibile utilizzare ~userper ottenere la home directory di user, ma nella maggior parte delle shell, che funziona solo per un set limitato di nomi utente (l'elenco dei caratteri consentiti nei nomi utente supportati per quell'operatore di ~espansione varia da shell a shell) e con diverse shell (incluso bash), ~$usernon funzioneranno (dovresti ricorrere a evalquando il nome dell'utente è memorizzato in una variabile lì). E dovresti ancora trovare un modo per ottenere l'elenco dei nomi utente.

Alcune shell hanno il supporto integrato per ottenere quell'elenco di nomi utente.

  • bash: compgen -urestituisce l'elenco degli utenti nei database che possono essere enumerati.
  • zsh: l' $userdirsarray associativo associa i nomi utente alla loro home directory (limitata anche ai database che possono essere enumerati, ma se si esegue ~userun'espansione per un utente che si trova in un database non enumerabile, verrà aggiunta una voce $userdirs). Quindi puoi fare:

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

    per elencare gli utenti con la loro home directory.

    Funziona solo quando zshè interattivo però .

  • tcsh, fishE yashsono altri tre coperture che possono completare i nomi utente (ad esempio quando il completamento ~<Tab>argomenti), ma non sembra ci hanno permesso di ottenere quella lista di nomi utente a livello di codice.


La sfida per l'OP sarà sapere se getentci sarà, il che immagino in una certa misura dipende dalla portata delle loro "altre macchine".
EightBitTony il

1
@EightBitTony, ho aggiunto perlun'alternativa.
Stéphane Chazelas,

1
Su Mac, è probabilmente qualcosa che coinvolge Open Directory.
SilverWolf - Ripristina Monica il

@seaturtle, perl -le 'while (@e = getpwent) {print $e[7]}'funziona perfettamente su macOS.
Stéphane Chazelas,

1
@FloHe, quelli sono nomi utente. La maggior parte degli utenti dei sistemi Unix sono utenti di sistemi speciali la cui vita è dedicata all'esecuzione di servizi di sistema. getent passwdti mostra il database degli utenti. Il primo campo è il nome utente, il sesto campo è la home directory degli utenti.
Stéphane Chazelas,

17

Un modo migliore per elencare le home directory degli utenti è analizzarle /etc/passwded estrarle da lì e non fare ipotesi su dove possano essere.

E a giudicare dal tuo secondo commento, in realtà vuoi che i nomi utente, non le loro home directory, nel qual caso, /etc/passwdsiano comunque una scelta migliore. Si noti che alcune macchine Linux / UNIX avranno altri meccanismi di autenticazione utente configurati (ad es. LDAP), quindi alla fine la query è più complessa di quanto si possa immaginare, ma /etc/passwdè un buon punto di partenza.


9
Vedi anche getentsui sistemi che lo supportano.
Kusalananda

6
Sì, getentè sempre meglio dell'analisi /etc/passwd(risolve il problema con "altri meccanismi di autenticazione dell'utente").
Stephen Kitt,

@Kusalananda Il problema con una getentsoluzione è che si presuppone che l'origine dati possa essere enumerata e non solo interrogata per un valore specifico. Questo è dettagliato nella risposta di Stéphane Chazelas a questa domanda , ma ho pensato di aggiungere un commento per chiunque abbia sfogliato questa pagina.
Andrew Henle,

7

La breve risposta :

compgen -u

La risposta media : poiché stai utilizzando bash, puoi elencare tutti i possibili completamenti per l' ~utilizzo compgen -A user. È un uso così comune, può essere abbreviato compgen -u. Come shell incorporato, compgennon ha una sua pagina man. Vedi invece bash (1) per la documentazione e leggi la sezione sul Completamento programmabile .

Un'alternativa più approfondita

Se sei estremamente preoccupato per la portabilità, potresti non essere nemmeno in grado di fare affidamento su altre macchine bash. In tal caso, procedere come segue:

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

Spiegazione La risposta lunga prova tutto, quindi funzionerà praticamente su qualsiasi sistema UNIX, indipendentemente dal fatto che utilizzi il nuovo /etc/nsswitch.conf (sia GNU / Linux che BSD getent), il tradizionale file flat passwd UNIX, MacOS Directory Services¹ ( dscl) o anche le versioni precedenti di MacOS X a tema cat e NeXTSTEP ( nidump).

Semplicità Ma quanto portatile ti serve? Unix ha molti modi di fare le cose e talvolta è più semplice. Se devi sceglierne uno, lo consiglierei getent passwd | cut -d: -f6per shell script.²


Nota a piè di pagina ¹: Non ho usato MacOS per un po ', quindi se qualcuno può confermare per me che ho ottenuto la sintassi corretta (e l'output non include alcun punto smarrito che rovinerebbe cut), sarebbe fantastico. Grazie.

Nota a piè di pagina ²: ciò che consiglio e ciò che faccio possono differire. Personalmente, userò più spesso il tradizionale cut -d: -f1 /etc/passwddalla riga di comando. Dopo decenni di ripetizione, le mie dita possono digitarlo mentre la mia mente sta lavorando su altre cose.


2
Tutte le macchine Mac OS X sono praticamente garantite per avere bash, come viene fornito con il sistema. (Come fa zsh e molte altre conchiglie.)
SilverWolf - Ripristina Monica il

Abbastanza vero, ma quando stavo usando MacOS, Apple non aggiornava bash da molto tempo ed era una cosa crusty versione 3 che dovevo sempre sostituire. Apple ha migliorato l'aggiornamento di bash?
hackerb9,


Vero, non ci ho pensato. La mia versione di bash (macOS Sierra 10.12.6) è 3.2.57. (:
SilverWolf - Ripristina Monica il

Comunque, bashè stato compgen -urilasciato dalla versione 2.04 nel 2000.
Stéphane Chazelas il

2

Che dire ls -l ~/..? Questo elenca tutte le directory nel genitore della tua home directory.


4
Funziona solo su sistemi in cui tutte le home directory sono basate nella stessa directory, che non è molte (potresti pensare che /homesia comune sui sistemi Linux, ma cosa succede quando lo esegui come root?). L'elenco delle home directory è un'avventura piena di insidie ​​se vuoi gestire tutti i casi che potresti incontrare, vedi le altre risposte per i dettagli.
Stephen Kitt,

7
Questa è probabilmente l'unica risposta finora che risponde direttamente al problema percepito dall'OP . Tuttavia, non risponde al problema di fondo di OP .
pipe

1
Il valore di questa risposta è capire cosa manca e perché non è buono come le altre risposte più votate.
Criggie l'
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.