Je veux lister tous les répertoires des utilisateurs sur la machine. Habituellement, je ferai:
ls -l /home
Mais je l'utilise dans un script qui sera déployé sur d'autres machines et peut-être que sur ces machines ils ne l'appellent pas à la maison (par exemple myHome). Je veux donc le généraliser ls -l ~
. Mais il répertorie simplement les répertoires personnels de mes utilisateurs au lieu du nom de tous les répertoires personnels des utilisateurs (en gros, je veux obtenir une liste des noms d'utilisateurs sur la machine). Comment généraliser?
bash
shell-script
eval
lakerda
la source
la source
~
c'est généralement l'équivalent de/home/user
, pas de/home
ou/home/*
(qui semble être plus proche de votre intention).nobody
) ont leur répertoire personnel défini sur/nonexistent
, qui, évidemment, n'existe pas. (Bien sûr, ces utilisateurs ont également leur hachage de mot de passe défini sur*
et leur shell défini sur/usr/sbin/nologin
ou/bin/false
, donc ils ne peuvent vraiment pas se connecter dans le sens normal pour commencer.)Réponses:
De nombreux systèmes ont une
getent
commande à la liste ou interroger le contenu des services Nom des bases de données commepasswd
,group
,services
,protocols
...Répertorierait les répertoires personnels (le champ délimité par le 6 e colon) de tous les utilisateurs des bases de données qui peuvent être énumérés .
Le nom d'utilisateur lui-même est dans le premier champ, donc pour la liste des noms d'utilisateurs:
(notez que cela ne signifie pas que ces utilisateurs peuvent se connecter au système ou que leur répertoire personnel a été créé, mais qu'ils sont connus du système, ils peuvent être traduits en un ID utilisateur).
Pour les bases de données qui ne peuvent pas être énumérées, vous pouvez essayer et interroger chaque identifiant utilisateur possible individuellement:
(ici en supposant que les uids s'arrêtent à 65535 (certains systèmes prennent en charge plus) et un shell qui prend en charge la
{x..y}
forme d'expansion d'accolade de zsh ). Mais vous ne voudriez pas le faire souvent sur des systèmes où la base de données utilisateur est en réseau (et la mise en cache locale est limitée) comme LDAP, NIS +, SQL ... car cela pourrait impliquer beaucoup de trafic réseau (et charger sur le serveur d'annuaire) ) pour effectuer toutes ces requêtes.Cela signifie également que si plusieurs utilisateurs partagent le même uid, vous n'aurez qu'une seule entrée pour chaque uid, alors manquez les autres.
Si vous n'en avez pas
getent
, vous pouvez recourir àperl
:pour
getent passwd
($e[0]
pour les noms d'utilisateur), ou:pour
getent passwd {0..65535}
les mêmes mises en garde.Dans les shells, vous pouvez utiliser
~user
pour obtenir le répertoire personnel deuser
, mais dans la plupart des shells, cela ne fonctionne que pour un ensemble limité de noms d'utilisateurs (la liste des caractères autorisés dans les noms d'utilisateurs pris en charge pour cet~
opérateur d'expansion varie d'un shell à l'autre) et avec plusieurs shells (y comprisbash
),~$user
ne fonctionneront pas (vous devrez y recourireval
lorsque le nom de l'utilisateur est stocké dans une variable là-bas). Et il vous faudrait encore trouver un moyen d'obtenir la liste des noms d'utilisateurs.Certains shells ont un support intégré pour obtenir cette liste de noms d'utilisateurs.
bash
:compgen -u
retournerait la liste des utilisateurs dans les bases de données qui peuvent être énumérées.zsh
: le$userdirs
tableau associatif mappe les noms d'utilisateurs à leur répertoire personnel (également limité aux bases de données qui peuvent être énumérées, mais si vous effectuez une~user
expansion pour un utilisateur qui se trouve dans une base de données non énumérable, une entrée sera ajoutée à$userdirs
). Vous pouvez donc faire:pour répertorier les utilisateurs avec leur répertoire personnel.
Cela ne fonctionne que quand il
zsh
est interactif .tcsh
,fish
Etyash
trois autres coquilles qui peuvent compléter les noms d'utilisateur (par exemple lors de l' achèvement des~<Tab>
arguments), mais il ne semble pas qu'ils vous permettent d' obtenir cette liste des noms d'utilisateur par programme.la source
getent
va y avoir, ce qui, dans une certaine mesure, dépend de l'étendue de leurs «autres machines».perl
alternative.perl -le 'while (@e = getpwent) {print $e[7]}'
fonctionne très bien sur macOS.getent passwd
vous montre la base de données utilisateur. Le premier champ est le nom d'utilisateur, le 6ème est le répertoire personnel des utilisateurs.Une meilleure façon de répertorier les répertoires personnels des utilisateurs consiste à analyser
/etc/passwd
et de les extraire de là, et de ne faire aucune hypothèse sur leur emplacement.Et à en juger par votre deuxième commentaire, vous voulez en fait que les noms d'utilisateurs, et non leurs répertoires personnels, dans ce cas,
/etc/passwd
soient de toute façon un meilleur choix. Notez que certaines machines Linux / UNIX auront d'autres mécanismes d'authentification utilisateur configurés (par exemple LDAP), et donc en fin de compte, votre requête est plus complexe que vous ne l'imaginez, mais/etc/passwd
c'est un bon point de départ.la source
getent
sur les systèmes qui le prennent en charge.getent
c'est toujours mieux que d'analyser/etc/passwd
(cela répond au problème des «autres mécanismes d'authentification des utilisateurs»).getent
solution est qu'elle suppose que la source de données peut être énumérée, et pas seulement interrogée pour une valeur spécifique. C'est détaillé dans la réponse de Stéphane Chazelas à cette question , mais je pense que j'ajouterais un commentaire à toute personne survolant cette page.La réponse courte :
La réponse moyenne : puisque vous utilisez
bash
, vous pouvez répertorier toutes les finitions possibles pour l'~
utilisationcompgen -A user
. C'est une telle utilisation courante, elle peut être abrégéecompgen -u
. En tant que shell intégré,compgen
n'a pas sa propre page de manuel. Voir plutôt bash (1) pour la documentation et lire la section sur la complétion programmable .Une alternative plus approfondie
Si vous êtes extrêmement préoccupé par la portabilité, vous ne pourrez peut-être même pas compter sur d'autres machines
bash
. Dans ce cas, procédez comme suit:Explication La réponse longue essaie tout, donc cela fonctionnera sur à peu près n'importe quel système UNIX, indépendamment du fait qu'il utilise le plus récent /etc/nsswitch.conf (GNU / Linux et BSD sont fournis avec
getent
), le fichier plat passwd UNIX traditionnel, MacOS Directory Services¹ (dscl
), ou même les versions plus anciennes de MacOS X sur le thème des chats et NeXTSTEP (nidump
).Simplicité Mais, comment avez-vous besoin de portable? Unix a plusieurs façons de faire les choses et suffit parfois plus simplement. Si vous devez en choisir un, je le recommanderais
getent passwd | cut -d: -f6
pour les scripts shell.²Note de bas de page ¹: Je n'ai pas utilisé MacOS depuis un petit moment, donc si quelqu'un peut confirmer pour moi que j'ai la bonne syntaxe (et que la sortie n'inclut pas de deux-points errants qui gâcheraient
cut
), ce serait génial. Merci.Note de bas de page ²: ce que je recommande et ce que je fais peut différer. Personnellement, j'utiliserai plus souvent le traditionnel
cut -d: -f1 /etc/passwd
sur la ligne de commande. Après des décennies de répétition, mes doigts peuvent taper pendant que mon esprit travaille sur d'autres choses.la source
bash
acompgen -u
depuis 2.04 sorti en 2000.Et alors
ls -l ~/..
? Ceci répertorie tous les répertoires dans le parent de votre répertoire personnel.la source
/home
c'est courant sur les systèmes Linux, mais que se passe-t-il lorsque vous exécutez cela en tant queroot
?). La liste des répertoires personnels est une aventure pleine d'embûches si vous voulez gérer tous les cas que vous rencontrerez probablement, voir les autres réponses pour plus de détails.