Jak mogę wyświetlić listę wszystkich nazw użytkowników i / lub katalogów domowych?


16

Chcę wyświetlić listę wszystkich katalogów użytkowników na komputerze. Zazwyczaj zrobię:

ls -l /home

Ale używam go w skrypcie, który zostanie wdrożony na innych komputerach i być może na tych komputerach nie nazywają go domem (np. MyHome). Więc chcę to uogólnić ls -l ~. Ale po prostu wyświetla listę katalogów domowych użytkowników zamiast nazwy katalogów domowych wszystkich użytkowników (w zasadzie chcę uzyskać listę nazw użytkowników na komputerze). Jak mogę to uogólnić?


19
W rzeczywistości nie ma gwarancji, że katalogi domowe wszystkich użytkowników są podkatalogami dowolnego katalogu.
hobbs

17
@ Hobbs lub że istnieją nawet do momentu zalogowania się użytkownika. Jest to jeden z tych pozornie prostych problemów, który bardzo szybko się komplikuje.
EightBitTony,

11
Pamiętaj, że ~ogólnie jest to odpowiednik /home/user, brak /homelub /home/*(które wydają się być bliższe twojej intencji).
Ethan Kamiński,

2
@EightBitTony: ... ani nie ma żadnej gwarancji, że katalog domowy w ogóle istnieje . Na przykład w mojej instalacji Ubuntu kilku użytkowników systemu (w tym nobody) ma ustawiony katalog domowy na /nonexistent, co oczywiście nie istnieje. (Oczywiście, ci użytkownicy mają również swoje hasło hash do zestawu *i ich powłoki zestaw do /usr/sbin/nologinlub /bin/false, tak naprawdę nie może zalogować się w normalnym znaczeniu, aby rozpocząć.)
Ilmari Karonen

1
Z drugiej strony (oldschoolowy) serwer NFS może obsługiwać katalogi domowe dla użytkowników, którzy nie znają swojego systemu operacyjnego z nazwy.
rackandboneman

Odpowiedzi:


45

Wiele systemów posiada getentkomendy do listy lub kwerendy zawartości nazwa usługi baz danych, takich jak passwd, group, services, protocols...

getent passwd | cut -d: -f6

Wyświetliłby katalogi domowe ( pole rozdzielone 6- tym dwukropkiem) wszystkich użytkowników w bazach danych, które można wyliczyć .

Sama nazwa użytkownika znajduje się w pierwszym polu, więc dla listy nazw użytkowników:

getent passwd | cut -d: -f1

(zwróć uwagę, że nie oznacza to, że ci użytkownicy mogą zalogować się do systemu lub utworzono ich katalog domowy, ale że są oni znani w systemie, mogą zostać przetłumaczeni na identyfikator użytkownika).

W przypadku baz danych, których nie można wyliczyć, możesz spróbować wysłać zapytanie do każdego możliwego identyfikatora użytkownika osobno:

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

(tutaj przy założeniu, że UID zatrzyma się na 65535 (niektóre systemy obsługują więcej) i powłoka, która obsługuje {x..y}formę rozwijania nawiasów przez Zsh). Ale nie chcesz tego robić często w systemach, w których baza danych użytkowników jest podłączona do sieci (a lokalne buforowanie jest ograniczone), takich jak LDAP, NIS +, SQL ... ponieważ może to oznaczać duży ruch sieciowy (i obciążenie serwera katalogów ), aby wykonać wszystkie te zapytania.

Oznacza to również, że jeśli kilku użytkowników korzysta z tego samego identyfikatora użytkownika, dostaniesz tylko jeden wpis dla każdego identyfikatora użytkownika, więc przegap inne.

Jeśli nie masz getent, możesz skorzystać z perl:

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

dla getent passwd( $e[0]dla nazw użytkowników) lub:

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

za getent passwd {0..65535}tymi samymi zastrzeżeniami.

W powłokach można użyć ~userkatalogu głównego user, ale w większości powłok, który działa tylko w przypadku ograniczonego zestawu nazw użytkowników (lista dozwolonych znaków w nazwach użytkowników obsługiwanych dla tego ~operatora rozszerzenia różni się w zależności od powłoki) kilka powłok (w tym bash) ~$usernie będzie działać (należy skorzystać z opcji, evalgdy nazwa użytkownika jest tam przechowywana w zmiennej). I nadal będziesz musiał znaleźć sposób na uzyskanie listy nazw użytkowników.

Niektóre powłoki mają wbudowaną obsługę pobierania tej listy nazw użytkowników.

  • bash: compgen -uzwraca listę użytkowników w bazach danych, które można wyliczyć.
  • zsh: $userdirstablica asocjacyjna odwzorowuje nazwy użytkowników na ich katalog domowy (ogranicza się również do baz danych, które można wyliczyć, ale jeśli wykonasz ~userrozszerzenie dla użytkownika znajdującego się w bazie danych, której nie można wyliczyć, pozycja zostanie dodana $userdirs). Możesz więc zrobić:

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

    aby wyświetlić listę użytkowników z ich katalogiem domowym.

    Działa to tylko wtedy, gdy zshjest interaktywne .

  • tcsh, fishA yashtrzy inne pociski, które mogą zakończyć nazwy użytkownika (na przykład przy wypełnianiu ~<Tab>argumentów), ale nie wygląda na to, że pozwalają uzyskać tę listę nazw użytkowników programowo.


Wyzwaniem dla PO będzie wiedzieć, czy getenttam będzie, co, jak sądzę, do pewnego stopnia zależy od zakresu ich „innych maszyn”.
EightBitTony,

1
@EightBitTony, dodałem perlalternatywę.
Stéphane Chazelas,

1
Na Macu prawdopodobnie jest to coś związanego z Open Directory.
SilverWolf - Przywróć Monikę

@seaturtle, perl -le 'while (@e = getpwent) {print $e[7]}'działa dobrze na macOS.
Stéphane Chazelas,

1
@FloHe, to są nazwy użytkowników. Większość użytkowników systemów Unix to specjalni użytkownicy systemu, których życie poświęcone jest uruchamianiu usług systemowych. getent passwdpokazuje bazę danych użytkowników. Pierwsze pole to nazwa użytkownika, szóste pole to katalog domowy użytkowników.
Stéphane Chazelas,

17

Lepszym sposobem wylistowania katalogów domowych użytkowników jest ich parsowanie /etc/passwdi wyodrębnianie z nich, a nie przyjmowanie żadnych założeń dotyczących ich lokalizacji.

Sądząc po drugim komentarzu, naprawdę chcesz nazwy użytkowników, a nie ich katalogi domowe, w którym to przypadku i tak /etc/passwdjest lepszym wyborem. Zauważ, że niektóre maszyny z systemem Linux / UNIX będą miały skonfigurowane inne mechanizmy uwierzytelniania użytkowników (np. LDAP), a zatem Twoje zapytanie jest bardziej złożone, niż można sobie wyobrazić, ale /etc/passwdjest dobrym miejscem do rozpoczęcia.


9
Zobacz także getentsystemy, które go obsługują.
Kusalananda

6
Tak, getentzawsze jest lepsze niż parsowanie /etc/passwd(rozwiązuje problem związany z „innymi mechanizmami uwierzytelniania użytkowników”).
Stephen Kitt,

@Kusalananda Problem z getentrozwiązaniem polega na tym, że źródło danych można wyliczyć, a nie tylko zapytać o konkretną wartość. Jest to szczegółowo opisane w odpowiedzi Stéphane'a Chazelasa na to pytanie , ale pomyślałem, że dodam komentarz dla każdego, kto przejrzy tę stronę.
Andrew Henle,

7

Krótka odpowiedź :

compgen -u

Średnia odpowiedź : ponieważ używasz bash, możesz wymienić wszystkie możliwe uzupełnienia ~użycia compgen -A user. To takie powszechne użycie, można je skrócić compgen -u. Jako wbudowana powłoka, compgennie ma własnej strony podręcznika. Zamiast tego zobacz dokumentację bash (1) i przeczytaj sekcję Programowalne zakończenie .

Bardziej dokładna alternatywa

Jeśli bardzo martwisz się przenośnością, możesz nawet nie być w stanie polegać na innych komputerach bash. W takim przypadku wykonaj następujące czynności:

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

Wyjaśnienie Długa odpowiedź próbuje wszystkiego, więc będzie działać na prawie każdym systemie UNIX, niezależnie od tego, czy używa nowszego /etc/nsswitch.conf (zarówno GNU / Linux, jak i BSD getent), tradycyjnego płaskiego pliku passwd UNIX, MacOS Usługi katalogowe¹ ( dscl), a nawet starsze wydania MacOS X o tematyce kota i NeXTSTEP ( nidump).

Prostota Ale jak bardzo potrzebujesz przenośności? Unix ma wiele sposobów robienia rzeczy, a czasem prostsze wystarczy. Jeśli musisz wybrać jeden, polecam getent passwd | cut -d: -f6dla skryptów powłoki .²


Przypis ¹: Nie używałem MacOS trochę, więc jeśli ktoś może dla mnie potwierdzić, że mam poprawną składnię (a wynik nie zawiera żadnych zbłąkanych dwukropków, które mogłyby zepsuć cut), byłoby świetnie. Dzięki.

Przypis ²: To, co polecam i co robię, może się różnić. Osobiście częściej używam tradycyjnego cut -d: -f1 /etc/passwdz wiersza poleceń. Po dziesięcioleciach powtarzania moje palce mogą pisać, podczas gdy mój umysł pracuje nad innymi rzeczami.


2
Wszystkie maszyny Mac OS X mają gwarancję bash, podobnie jak system. (Podobnie jak Zsh i kilka innych powłok.)
SilverWolf - Przywróć Monikę

To prawda, ale w czasach, gdy korzystałem z systemu MacOS, Apple nie aktualizowało basha od dłuższego czasu i była to chrupiąca wersja 3, którą zawsze musiałem zastępować. Czy Apple poprawiło się w aktualizacji basha?
hackerb9


To prawda, nie myślałem o tym. Moja wersja bash (macOS Sierra 10.12.6) to 3.2.57. (:
SilverWolf - Przywróć Monikę

Tak czy bashcompgen -u
inaczej

2

Co ls -l ~/..? Wyświetla listę wszystkich katalogów nadrzędnych katalogu domowego.


4
Działa to tylko w systemach, w których wszystkie katalogi domowe znajdują się w tym samym katalogu, co nie jest wiele (może się wydawać, że /homejest powszechne w systemach Linux, ale co się stanie, gdy uruchomisz to jako root?). Listowanie katalogów domowych to przygoda pełna pułapek, jeśli chcesz poradzić sobie ze wszystkimi przypadkami, które możesz napotkać, zobacz inne odpowiedzi, aby uzyskać szczegółowe informacje.
Stephen Kitt

7
Jest to prawdopodobnie jedyna jak dotąd odpowiedź, która bezpośrednio odpowiada na postrzegany problem PO . Nie rozwiązuje to jednak problemu podstawowego OP .
rura

1
Wartość tej odpowiedzi polega na zrozumieniu tego, czego brakuje, i dlaczego nie jest tak dobra, jak inne wyżej głosowane odpowiedzi.
Criggie,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.