Saya ingin daftar semua pengguna dirs di mesin. Biasanya, saya akan melakukan:
ls -l /home
Tapi saya menggunakannya dalam skrip yang akan digunakan pada mesin lain dan mungkin pada mesin itu mereka tidak menyebutnya rumah (misalnya myHome). Jadi saya ingin menggeneralisasikannya ls -l ~
. Tapi itu hanya daftar pengguna saya dir home bukannya semua nama pengguna home dirs (pada dasarnya saya ingin mendapatkan daftar nama-nama pengguna di mesin). Bagaimana saya bisa menggeneralisasikannya?
bash
shell-script
eval
lakerda
sumber
sumber
~
umumnya setara dengan/home/user
, bukan/home
atau atau/home/*
(yang tampaknya lebih dekat dengan niat Anda).nobody
) memiliki direktori home mereka diatur ke/nonexistent
, yang, jelas, tidak ada. (Tentu saja, para pengguna juga memiliki hash sandi yang ditetapkan*
dan shell mereka diatur ke/usr/sbin/nologin
atau/bin/false
, sehingga mereka benar-benar tidak dapat masuk dalam pengertian normal untuk memulai.)Jawaban:
Banyak sistem memiliki
getent
perintah untuk daftar atau query isi Name Service database sepertipasswd
,group
,services
,protocols
...Akan mencantumkan direktori home (bidang ke- 6 dengan batas kolon ke- 6 ) dari semua pengguna dalam basis data yang dapat disebutkan .
Nama pengguna itu sendiri ada di bidang pertama, jadi untuk daftar nama pengguna:
(perhatikan bahwa itu tidak berarti para pengguna dapat login ke sistem atau direktori home mereka telah dibuat, tetapi mereka dikenal oleh sistem, mereka dapat diterjemahkan ke id pengguna).
Untuk basis data yang tidak dapat disebutkan, Anda dapat mencoba dan menanyakan setiap id pengguna yang memungkinkan secara individual:
(disini anggaplah uids berhenti di 65535 (beberapa sistem mendukung lebih) dan sebuah shell yang mendukung
{x..y}
bentuk ekspansi brace zsh ). Tetapi Anda tidak ingin sering melakukannya pada sistem di mana basis data pengguna jaringan (dan ada caching lokal terbatas) seperti LDAP, NIS +, SQL ... karena hal itu dapat menyiratkan banyak lalu lintas jaringan (dan memuat pada server direktori ) untuk membuat semua pertanyaan itu.Itu juga berarti bahwa jika ada beberapa pengguna berbagi uid yang sama, Anda hanya akan mendapatkan satu entri untuk setiap uid, jadi lewatkan yang lain.
Jika tidak
getent
, Anda dapat menggunakanperl
:untuk
getent passwd
($e[0]
untuk nama pengguna), atau:untuk
getent passwd {0..65535}
dengan peringatan yang sama.Dalam shell, Anda dapat menggunakan
~user
untuk mendapatkan direktori homeuser
, tetapi di sebagian besar shell, yang hanya berfungsi untuk sekumpulan nama pengguna yang terbatas (daftar karakter yang diizinkan dalam nama pengguna yang didukung untuk~
operator ekspansi itu bervariasi dari shell ke shell) dan dengan beberapa shell (termasukbash
),~$user
tidak akan berfungsi (Anda harus menggunakaneval
ketika nama pengguna disimpan dalam variabel di sana). Dan Anda masih harus menemukan cara untuk mendapatkan daftar nama pengguna.Beberapa shell memiliki dukungan bawaan untuk mendapatkan daftar nama pengguna itu.
bash
:compgen -u
akan mengembalikan daftar pengguna dalam basis data yang dapat disebutkan.zsh
:$userdirs
array asosiatif memetakan nama pengguna ke direktori home mereka (juga terbatas pada basis data yang dapat disebutkan, tetapi jika Anda melakukan~user
ekspansi untuk pengguna yang ada dalam basis data yang tidak dapat dihitung, entri akan ditambahkan ke$userdirs
). Jadi kamu bisa melakukan:untuk daftar pengguna dengan direktori home mereka.
Itu hanya berfungsi ketika
zsh
bersifat interaktif sekalipun .tcsh
,fish
danyash
tiga shell lain yang dapat melengkapi nama pengguna (misalnya saat menyelesaikan~<Tab>
argumen), tetapi sepertinya mereka tidak membiarkan Anda memperoleh daftar nama pengguna tersebut secara terprogram.sumber
getent
akan ada di sana, yang menurut saya sedikit banyak tergantung pada ruang lingkup 'mesin lain' mereka.perl
alternatif.perl -le 'while (@e = getpwent) {print $e[7]}'
berfungsi dengan baik di macOS.getent passwd
menunjukkan kepada Anda basis data pengguna. Bidang pertama adalah nama pengguna, bidang ke-6 adalah direktori home pengguna.Cara yang lebih baik untuk membuat daftar direktori home pengguna, adalah mem
/etc/passwd
- parsing dan mengekstraknya dari sana, dan tidak membuat asumsi tentang di mana mereka berada.Dan menilai dari komentar kedua Anda, Anda sebenarnya menginginkan nama pengguna, bukan direktori home mereka, dalam hal ini, bagaimanapun,
/etc/passwd
adalah pilihan yang lebih baik. Perhatikan bahwa beberapa mesin Linux / UNIX akan memiliki mekanisme otentikasi pengguna lain yang dikonfigurasikan (mis. LDAP), dan pada akhirnya, kueri Anda lebih kompleks daripada yang Anda bayangkan, tetapi/etc/passwd
merupakan tempat yang baik untuk memulai.sumber
getent
pada sistem yang mendukungnya.getent
selalu lebih baik daripada parsing/etc/passwd
(ini mengatasi masalah dengan "mekanisme otentikasi pengguna lain").getent
solusi adalah mengasumsikan sumber data dapat disebutkan, dan tidak hanya ditanya untuk nilai tertentu. Itu terinci dalam jawaban Stéphane Chazelas untuk pertanyaan ini , tapi saya rasa saya akan menambahkan komentar untuk siapa pun yang membaca halaman ini.Jawaban singkatnya :
Jawaban menengah : Karena Anda menggunakan
bash
, Anda dapat membuat daftar semua kemungkinan penyelesaian untuk~
digunakancompgen -A user
. Itu penggunaan yang umum, bisa disingkatcompgen -u
. Sebagai shell builtin,compgen
tidak memiliki halaman manualnya sendiri. Alih-alih lihat bash (1) untuk dokumentasi dan baca bagian tentang Programmable Completion .Alternatif yang lebih menyeluruh
Jika Anda sangat khawatir tentang portabilitas, Anda bahkan mungkin tidak dapat mengandalkan mesin lain
bash
. Dalam hal ini, lakukan ini:Penjelasan Jawaban panjangnya mencoba semuanya, jadi itu akan bekerja pada hampir semua sistem UNIX, terlepas dari apakah ia menggunakan /etc/nsswitch.conf yang lebih baru (baik GNU / Linux dan BSD datang bersama
getent
), file flat passwd UNIX tradisional, MacOS's Layanan Direktori¹ (dscl
), atau bahkan rilis MacOS X bertema kucing dan NeXTSTEP (nidump
).Kesederhanaan Tapi, seberapa portabel yang Anda butuhkan? Unix memiliki banyak cara untuk melakukan sesuatu dan terkadang cukup sederhana. Jika Anda harus memilih satu, saya akan merekomendasikan
getent passwd | cut -d: -f6
untuk skrip shell. ²Catatan Kaki ¹: Saya belum pernah menggunakan MacOS sedikit pun, jadi jika seseorang dapat mengonfirmasi untuk saya bahwa saya sudah benar sintaks (dan output tidak termasuk sembarang titik dua yang akan mengacaukan
cut
), itu akan bagus. Terima kasih.Catatan kaki ²: Apa yang saya rekomendasikan dan apa yang saya lakukan mungkin berbeda. Secara pribadi, saya akan lebih sering menggunakan tradisional
cut -d: -f1 /etc/passwd
di baris perintah. Setelah beberapa dekade pengulangan, jari-jari saya dapat mengetiknya sementara pikiran saya mengerjakan hal-hal lain.sumber
bash
sudahcompgen -u
sejak 2.04 dirilis pada tahun 2000.Bagaimana dengan
ls -l ~/..
? Ini mencantumkan semua direktori di induk direktori home Anda.sumber
/home
umum pada sistem Linux, tetapi apa yang terjadi ketika Anda menjalankannya sebagairoot
?). Mendaftar direktori home adalah petualangan penuh jebakan jika Anda ingin menangani semua kasus yang mungkin Anda temui, lihat jawaban lain untuk detailnya.