Temukan pemilik direktori atau file, tetapi hanya kembalikan itu dan tidak ada yang lain

62

Saya mencari perintah yang akan mengembalikan pemilik direktori dan hanya itu - seperti regex parsing ls -latperintah atau yang serupa? Saya ingin menggunakan hasilnya di skrip lain.

Jason
sumber

Jawaban:

102

stat dari GNU coreutils dapat melakukan ini:

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

Sayangnya, ada beberapa versi stat, dan tidak ada banyak konsistensi dalam sintaksis mereka. Sebagai contoh, pada FreeBSD, itu akan menjadi

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

Jika portabilitas menjadi perhatian, Anda mungkin lebih baik menggunakan saran Gilles untuk menggabungkan lsdan awk. Itu harus memulai dua proses, bukan satu, tetapi memiliki keuntungan menggunakan hanya fungsi standar POSIX:

ls -ld /path/of/file/or/directory | awk '{print $3}'
cjm
sumber
2
stat -c% U / jalur, jika singkatnya adalah bonus.
tsvallender
1
Itu mengasumsikan stat GNU, yang tidak terjadi pada sistem Linux yang lebih lama (bahkan pada sistem yang lebih baru saya akan waspada, mungkin ada yang berbeda stat(standar situs-lebar) di /usr/local/binatau di suatu tempat di rumah pengguna), dan jarang tersedia di unix lain.
Gilles 'SO- stop being evil'
1
stat -c %Umemiliki keuntungan juga bekerja dengan BusyBox , jika statperintah dikompilasi.
Gilles 'SO- stop being evil'
1
Bagus, contoh terakhir (ls) berfungsi baik di Unix / OSX dan Linux
kenorb
1
Perhatikan bahwa ls akan mencetak uid jika tidak ada pengguna lokal yang cocok dengan pemilik (mis., Pada jaringan berbagi), tetapi stat -c '%U' DIRakan mencetak UNKNOWN, yang kurang bermanfaat atau lebih tepat, tergantung pada bagaimana Anda melihatnya.
basic6
18

Mem-parsing output lsjarang merupakan ide yang bagus , tetapi mendapatkan beberapa bidang pertama adalah pengecualian, itu benar-benar berfungsi pada semua "tradisional" (tidak bekerja pada platform seperti beberapa implementasi Windows yang memungkinkan spasi dalam nama pengguna).

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

Pilihan lain adalah dengan menggunakan statperintah, tetapi masalah statdari shell adalah bahwa ada beberapa perintah dengan sintaks yang berbeda, sehingga statdalam skrip shell tidak dapat diport (bahkan di seluruh instalasi Linux).

Perhatikan bahwa pengujian apakah pengguna yang diberikan adalah pemilik adalah proposisi yang berbeda.

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 'SANGAT berhenti menjadi jahat'
sumber
ls | awkSayangnya, ada beberapa peringatan dengan pendekatannya, seperti yang telah saya catat di sini . Saya belum datang dengan solusi untuk, "file target / dir adalah symlink dengan nama yang berbeda," masalah yang saya sebutkan dalam komentar terakhir saya.
beporter
Alih-alih find . -user "$username" -print -prune -o -pruneAnda bisa melakukannyafind . -maxdepth 0 -user "$username"
Niklas Holm
@Gilles Apakah ada alasan Anda menggunakan awk 'NR==1 {print $3}'bukan hanya awk '{print $3}'? Saya tidak yakin mengapa NR==1ini perlu di sini.
Harold Fischer
1
@ HaroldFischer Hanya dalam kasus tepi di mana path berisi baris baru. Ini jarang diperlukan, tetapi tidak pernah berbahaya.
Gilles 'SO- stop being evil'
@Gilles Sangat senang tahu !! Hanya ingin tahu, apakah Anda mengetahui implementasi di lsmana baris baru di jalur menyebabkan garis terpecah menjadi dua (yang saya percaya adalah tepi kasus yang Anda coba tutupi)? Pada GNU ls(versi agak baru), BusyBox lsdan FreeBSD lsbaris baru dikembalikan sebagai $'\n', ?dan ?masing-masing.
Harold Fischer
9

Anda juga dapat melakukan ini dengan GNU find:

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

Ini bukan portable di luar sistem GNU, tetapi saya akan terkejut menemukan distribusi Linux yang tidak berfungsi.

mattdm
sumber
1
Ini berfungsi pada setiap sistem Linux yang tidak tertanam dan beberapa lainnya (mis. Cygwin). Sistem tertanam kemungkinan memiliki Busybox , yang findtidak memilikinya -printf.
Gilles 'SO- stop being evil'
Seperti yang saya katakan, sistem GNU.
mattdm
Sistem tanpa GNU coreutils (seperti FreeBSD) tidak memiliki -printf:-(.
pevik
@pevik Ya, seperti yang saya katakan, masih. Tetapi Anda dapat menginstal GNU find jika Anda membutuhkannya. :)
mattdm
@mattdm: tidak selalu :-(. Yang paling penting ketika Anda menulis skrip yang harus portabel.
pevik
2

Dalam bash murni Anda dapat mengkonversi output lske array dan indeks ke dalamnya.

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

Ini tidak elegan seperti menggunakan stat, findatau awk, tetapi bisa bekerja dalam keadaan darurat.

codehearts
sumber