Znajdź właściciela katalogu lub pliku, ale zwróć tylko to i nic więcej

62

Szukam polecenia, które zwróci właściciela katalogu i tylko to - takie jak wyrażenie regularne analizujące ls -latpolecenie lub coś podobnego? Chcę użyć wyniku w innym skrypcie.

Jason
źródło

Odpowiedzi:

102

stat z GNU coreutils może to zrobić:

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

Niestety istnieje wiele wersji stati ich składnia nie jest zbyt spójna. Na przykład na FreeBSD

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

Jeśli problemem jest przenośność, prawdopodobnie lepiej skorzystasz z sugestii Gillesa dotyczącej połączenia lsi awk. Musi uruchomić dwa procesy zamiast jednego, ale ma tę zaletę, że używa tylko funkcjonalności zgodnej ze standardem POSIX:

ls -ld /path/of/file/or/directory | awk '{print $3}'
cjm
źródło
2
stat -c% U / ścieżka, jeśli zwięzłość jest bonusem.
tsvallender
1
To zakłada statystykę GNU, co nie ma miejsca w starszych systemach Linux (nawet na nowszych systemach byłbym ostrożny, może istnieć inny stat(standard dla całej witryny) w /usr/local/bindomu użytkownika lub gdzieś) i jest rzadko dostępny na innych jednorożcach.
Gilles
1
stat -c %Uma tę zaletę, że współpracuje również z BusyBox , jeśli statpolecenie jest wkompilowane.
Gilles
1
Fajny, ostatni przykład (ls) działa zarówno na systemach Unix / OSX, jak i Linux
kenorb
1
Zauważ, że ls wydrukuje identyfikator użytkownika, jeśli nie ma lokalnego użytkownika pasującego do właściciela (tj. W udziale sieciowym), ale stat -c '%U' DIRwydrukuje UNKNOWN, co jest mniej pomocne lub bardziej odpowiednie, w zależności od tego, jak na to patrzysz.
podstawowe6
18

Parsowanie danych wyjściowych lsrzadko jest dobrym pomysłem , ale uzyskanie pierwszych kilku pól jest wyjątkiem, w rzeczywistości działa na wszystkich „tradycyjnych” unikach (nie działa na platformach takich jak niektóre implementacje Windows, które dopuszczają spacje w nazwach użytkowników).

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

Inną opcją jest użycie statpolecenia, ale problem z statpowłoką polega na tym, że istnieje wiele poleceń o różnej składni, więc statw skrypcie powłoki nie można importować (nawet w różnych instalacjach Linuksa).

Pamiętaj, że sprawdzenie, czy dany użytkownik jest właścicielem, jest inną propozycją.

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
źródło
ls | awkNiestety, istnieje pewne zastrzeżenie dotyczące tego podejścia, jak zauważyłem tutaj . Nie znalazłem jeszcze rozwiązania dla problemu: „plik docelowy / katalog to dowiązanie symboliczne o innej nazwie”, o którym wspomniałem w moim ostatnim komentarzu.
beporter
Zamiast tego find . -user "$username" -print -prune -o -prunemożesz po prostu zrobićfind . -maxdepth 0 -user "$username"
Niklas Holm,
@Gilles Czy jest jakiś powód, dla którego używasz awk 'NR==1 {print $3}'zamiast tylko awk '{print $3}'? Nie jestem pewien, dlaczego NR==1jest to konieczne tutaj.
Harold Fischer,
1
@HaroldFischer Tylko w przypadku krawędzi, w której ścieżka zawiera nowy wiersz. Jest to rzadko konieczne, ale nigdy szkodliwe.
Gilles
@Gilles Bardzo dobrze wiedzieć !! Ciekawe, czy zdajesz sobie sprawę z tego, lsgdzie nowa linia na ścieżce powoduje podział linii na dwie części (co moim zdaniem jest przypadkiem krawędzi, który próbujesz pokryć)? Na GNU ls(wersja nowymi), BusyBox lsi FreeBSD lsnowej linii jest zwracany jako $'\n', ?i ?, odpowiednio.
Harold Fischer,
9

Można to również zrobić za pomocą GNU find:

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

Nie jest to przenośne poza systemem GNU, ale zdziwiłbym się, gdy znalazł dystrybucję Linuksa, w której nie działa.

mattdm
źródło
1
Działa to na każdym niewbudowanym systemie Linux i kilku innych (np. Cygwin). Systemy wbudowane prawdopodobnie mają Busybox , którego findnie ma -printf.
Gilles
Tak jak powiedziałem, system GNU.
mattdm
Systemy bez coreutils GNU (takie jak FreeBSD) nie mają -printf:-(.
pevik
@pevik Tak, jak powiedziałem, wciąż. Ale możesz zainstalować GNU find, jeśli go potrzebujesz. :)
mattdm
@mattdm: nie zawsze :-(. co najważniejsze, kiedy piszesz skrypty, które powinny być przenośne.
pevik
2

W czystym bashu możesz przekonwertować dane wyjściowe lsna tablicę i indeksować do niej.

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

To nie jest tak elegancki jak używanie stat, findalbo awk, ale może pracować w kropce.

serca kodowe
źródło