Suchen Sie den Eigentümer eines Verzeichnisses oder einer Datei, geben Sie diesen und nichts anderes zurück

62

Ich suche einen Befehl, der den Eigentümer eines Verzeichnisses zurückgibt und nur diesen - wie eine Regex, die den ls -latBefehl analysiert, oder etwas Ähnliches? Ich möchte das Ergebnis in einem anderen Skript verwenden.

Jason
quelle

Antworten:

102

stat von GNU Coreutils können dies tun:

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

Leider gibt es eine Reihe von Versionen von statund es gibt nicht viel Konsistenz in ihrer Syntax. Zum Beispiel unter FreeBSD

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

Wenn es um Portabilität geht, ist es wahrscheinlich besser, Gilles 'Vorschlag zu kombinieren lsund zu verwenden awk. Es muss zwei Prozesse anstelle von einem starten, hat jedoch den Vorteil, dass nur die POSIX-Standardfunktionalität verwendet wird:

ls -ld /path/of/file/or/directory | awk '{print $3}'
cjm
quelle
2
stat -c% U / path, wenn Kürze ein Bonus ist.
tsvallender
1
Das setzt GNU stat voraus, was auf älteren Linux-Systemen nicht der Fall ist (selbst auf neueren Systemen wäre ich vorsichtig, es könnte einen anderen stat(einen Site-weiten Standard) in /usr/local/binoder irgendwo im Haus des Benutzers geben) und er ist selten verfügbar auf anderen unices.
Gilles 'SO- hör auf böse zu sein'
1
stat -c %Uhat den Vorteil, auch mit BusyBox zu arbeiten , wenn der statBefehl in kompiliert ist.
Gilles 'SO - hör auf, böse zu sein'
1
Nizza, das letzte Beispiel (ls) funktioniert sowohl unter Unix / OSX als auch unter Linux
Kenorb 28.11.13
1
Beachten Sie, dass ls die Benutzer-ID druckt, wenn kein lokaler Benutzer mit dem Besitzer übereinstimmt (dh auf einer Netzwerkfreigabe), aber stat -c '%U' DIRgedruckt wird UNKNOWN, was je nach Ansicht weniger hilfreich oder angemessener ist.
basic6
18

Das Parsen der Ausgabe von lsist selten eine gute Idee , aber das Erhalten der ersten Felder ist eine Ausnahme, es funktioniert tatsächlich auf allen "traditionellen" Unices (es funktioniert nicht auf Plattformen wie einigen Windows-Implementierungen, die Leerzeichen in Benutzernamen zulassen).

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

Eine andere Option ist die Verwendung eines statBefehls. Das Problem mit statder Shell besteht jedoch darin, dass mehrere Befehle mit unterschiedlicher Syntax vorhanden sind, sodass statein Shell-Skript nicht portierbar ist (auch nicht für Linux-Installationen).

Beachten Sie, dass das Testen, ob ein bestimmter Benutzer der Eigentümer ist, eine andere Angelegenheit ist.

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 'SO - hör auf böse zu sein'
quelle
ls | awkLeider gibt es auch einige Vorbehalte bei der Herangehensweise, wie ich hier bemerkt habe . Ich habe noch keine Lösung für das Problem "Zieldatei / Verzeichnis ist ein Symlink mit einem anderen Namen" gefunden, das ich kürzlich in meinem Kommentar erwähnt habe.
beporter
Stattdessen find . -user "$username" -print -prune -o -prunekönnten Sie einfach tunfind . -maxdepth 0 -user "$username"
Niklas Holm
@ Gilles Gibt es einen Grund, den du verwendest awk 'NR==1 {print $3}'anstatt nur awk '{print $3}'? Ich bin mir nicht sicher, warum das NR==1hier notwendig ist.
Harold Fischer
1
@HaroldFischer Nur in einem Randfall, in dem der Pfad eine neue Zeile enthält. Es ist selten notwendig, aber niemals schädlich.
Gilles 'SO - hör auf böse zu sein'
@ Gilles Sehr gut zu wissen !! Nur neugierig, sind Sie sich einer Implementierung bewusst, bei der lseine neue Zeile in einem Pfad dazu führt, dass die Zeile in zwei Teile geteilt wird (was meiner Meinung nach der Randfall ist, den Sie abdecken möchten)? Auf GNU ls(neuere Version), BusyBox lsund FreeBSD lsist ein Newline zurückgeführt, wie $'\n', ?und ?, respectively.
Harold Fischer
9

Das kann man auch mit GNU find machen:

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

Dies ist außerhalb des GNU-Systems nicht portierbar, aber ich wäre überrascht, eine Linux-Distribution zu finden, bei der es nicht funktioniert.

mattdm
quelle
1
Dies funktioniert auf jedem nicht eingebetteten Linux-System und einigen anderen (z. B. Cygwin). Eingebettete Systeme verfügen wahrscheinlich über eine Busybox , für die finddies nicht der Fall ist -printf.
Gilles 'SO- hör auf böse zu sein'
Wie ich schon sagte, GNU-System.
Mattdm
Systeme ohne GNU-Coreutils (wie FreeBSD) haben nicht -printf:-(.
Pevik
@pevik Ja, wie ich schon sagte, immer noch. Sie können GNU find jedoch installieren, wenn Sie es benötigen. :)
Mattdm
@mattdm: nicht immer :-(. am wichtigsten, wenn Sie Skripte schreiben, die portabel sein sollten.
Pevik
2

In pure bash können Sie die Ausgabe von lsin ein Array konvertieren und in dieses indexieren.

# (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

Es ist nicht so elegant wie die Verwendung von stat, findoder awk, könnte aber zur Not funktionieren.

Codehearts
quelle