Trouver le propriétaire d'un répertoire ou d'un fichier, mais ne renvoyer que cela et rien d'autre

62

Je cherche une commande qui renverra le propriétaire d'un répertoire et seulement cela - comme une expression régulière analysant la ls -latcommande ou quelque chose de similaire? Je veux utiliser le résultat dans un autre script.

Jason
la source

Réponses:

102

stat de GNU coreutils peuvent le faire:

stat -c '%U' /path/of/file/or/directory

Malheureusement, il existe plusieurs versions de stat, et leur syntaxe n’est pas très cohérente. Par exemple, sur FreeBSD, ce serait

stat -f '%Su' /path/of/file/or/directory

Si la portabilité est une préoccupation, vous feriez probablement mieux d'utiliser la suggestion de Gilles de combiner lset awk. Il doit démarrer deux processus au lieu d'un, mais il présente l'avantage d'utiliser uniquement les fonctionnalités standard POSIX:

ls -ld /path/of/file/or/directory | awk '{print $3}'
cjm
la source
2
stat -c% U / chemin, si la brièveté est un bonus.
tsvallender
1
Cela suppose GNU stat, ce qui n’est pas le cas sur les systèmes Linux plus anciens (même sur des systèmes plus récents, méfiez-vous, il pourrait y avoir un autre stat(un standard du site) dans /usr/local/binou quelque part dans la maison de l’utilisateur), et est rarement disponible sur d'autres unices.
Gilles, arrête de faire le mal
1
stat -c %Ua l'avantage de travailler également avec BusyBox , si la statcommande est compilée.
SO 'Gilles, arrête d'être méchant'
1
Bien, le dernier exemple (ls) fonctionne à la fois sous Unix / OSX et Linux
kenorb
1
Notez que ls imprimera l'ID utilisateur si aucun utilisateur local ne correspond au propriétaire (c'est-à-dire sur un partage réseau), mais stat -c '%U' DIRimprimera UNKNOWN, ce qui est moins utile ou plus approprié, selon votre apparence.
basic6
18

L’analyse de la sortie de lsest rarement une bonne idée , mais l’obtention des premiers champs est une exception, elle fonctionne en fait sur tous les unices «traditionnels» (elle ne fonctionne pas sur des plates-formes telles que certaines implémentations Windows qui autorisent des espaces dans les noms d’utilisateur).

ls -ld /path/to/directory | awk 'NR==1 {print $3}'

Une autre option consiste à utiliser une statcommande, mais le problème posé par statle shell réside dans le fait qu'il existe plusieurs commandes avec une syntaxe différente, de sorte statqu'un script de shell est non exportable (même sur les installations Linux).

Notez que tester si un utilisateur donné est le propriétaire est une proposition différente.

if [ -n "$(find . -user "$username" -print -prune -o -prune)" ]; then
  echo "The current directory is owned by $username."
fi
if [ -n "$(find . -user "$(id -u)" -print -prune -o -prune)" ]; then
  echo "The current directory is owned by the current user."
fi
Gilles, arrête de faire le mal
la source
ls | awkMalheureusement, comme je l’ai déjà noté ici, il y a certaines mises en garde concernant cette approche . Je n'ai pas encore trouvé de solution pour le problème "le fichier / répertoire cible est un lien symbolique portant un nom différent", problème que j'ai mentionné dans mon récent commentaire.
beporter
Au lieu de find . -user "$username" -print -prune -o -prunevous pourriez simplement le fairefind . -maxdepth 0 -user "$username"
Niklas Holm
@ Gilles Y a-t-il une raison que vous utilisiez awk 'NR==1 {print $3}'au lieu de juste awk '{print $3}'? Je ne sais pas pourquoi NR==1c'est nécessaire ici.
Harold Fischer
1
@HaroldFischer Uniquement dans les cas où le chemin contient une nouvelle ligne. C'est rarement nécessaire, mais jamais nuisible.
Gilles 'SO- arrête d'être méchant'
@Gilles Très bon à savoir !! Juste curieux, êtes-vous au courant d'une implémentation dans lslaquelle une nouvelle ligne dans un chemin provoque la scission de la ligne en deux (ce qui, je crois, est le cas extrême que vous essayez de couvrir)? Sous GNU ls(version nouvelle), BusyBox lset FreeBSD, lsune nouvelle ligne est renvoyée sous la forme $'\n', ?et ?.
Harold Fischer
9

On peut aussi le faire avec GNU find:

find $directoryname -maxdepth 0 -printf '%u\n'

Ce n’est pas portable en dehors du système GNU, mais je serais surpris de trouver une distribution Linux où cela ne fonctionne pas.

mattdm
la source
1
Cela fonctionne sur tous les systèmes Linux non intégrés et quelques autres (par exemple Cygwin). Les systèmes embarqués sont susceptibles d’avoir Busybox , dont findn’a pas -printf.
Gilles 'SO- arrête d'être méchant'
Comme je l'ai dit, le système GNU.
Mattdm
Les systèmes sans coreutils GNU (tels que FreeBSD) ne possèdent pas -printf:-(.
pevik
@pevik Ouais, comme je l'ai dit, toujours. Mais vous pouvez installer GNU find si vous en avez besoin. :)
mattdm
@mattdm: pas toujours :-(. surtout lorsque vous écrivez des scripts qui devraient être portables.
pevik
2

En bash pur, vous pouvez convertir la sortie de lsen un tableau et l’indexer.

# (lrwxr-xr-x, 1, myuser, staff, 36, Oct, 21, 16:36, /path/to/file)    
file_meta=($(ls -ld /path/to/file))
file_owner="${file_meta[2]}" # myuser

Il est pas aussi élégant que l' utilisation stat, findou awk, mais pourrait travailler dans un pincement.

les cœurs de code
la source