ฉันจะแสดงชื่อผู้ใช้และ / หรือโฮมไดเร็กตอรี่ทั้งหมดได้อย่างไร?


16

ฉันต้องการแสดงรายการผู้ใช้ทั้งหมดบนเครื่องโดยปกติแล้วฉันจะทำ:

ls -l /home

แต่ฉันใช้มันในสคริปต์ที่จะติดตั้งบนเครื่องอื่นและอาจใช้กับเครื่องที่พวกเขาไม่เรียกมันว่าบ้าน (เช่น myHome) ls -l ~ดังนั้นผมจึงต้องการที่จะพูดคุยมัน แต่มันจะแสดงรายชื่อผู้ใช้ที่บ้านของฉันแทนที่จะเป็นชื่อผู้ใช้ที่บ้าน (โดยทั่วไปฉันต้องการรับรายชื่อผู้ใช้บนเครื่อง) ฉันจะพูดคุยเรื่องนี้ได้อย่างไร


19
ในความเป็นจริงไม่รับประกันว่าไดเรกทอรีบ้านของผู้ใช้ทั้งหมดเป็นไดเรกทอรีย่อยของไดเรกทอรีใดไดเรกทอรีหนึ่ง
ฮอบส์

17
@ ฮอบส์หรือพวกเขายังคงมีอยู่จนกว่าผู้ใช้จะเข้าสู่ระบบนี่เป็นหนึ่งในปัญหาง่ายๆที่เห็นได้ชัดว่าซับซ้อนอย่างรวดเร็ว
EightBitTony

11
โปรดทราบว่า~โดยทั่วไปเทียบเท่า/home/userไม่ใช่/homeหรือ/home/*(ซึ่งดูเหมือนจะได้ใกล้ชิดกับความตั้งใจของคุณ)
Ethan Kaminski

2
@EightBitTony: ... และไม่มีการรับประกันใด ๆ ที่ไดเรกทอรีบ้านที่มีอยู่ในทุก ตัวอย่างเช่นในการติดตั้ง Ubuntu ของฉันผู้ใช้ระบบหลายคน (รวมถึงnobody) มีการตั้งค่าโฮมไดเรกทอรีของพวกเขา/nonexistentซึ่งแน่นอนไม่มีอยู่ (แน่นอนว่าผู้ใช้เหล่านั้นมีแฮชรหัสผ่าน*และเชลล์ของพวกเขาตั้งค่าเป็น/usr/sbin/nologinหรือ/bin/falseดังนั้นพวกเขาจึงไม่สามารถเข้าสู่ระบบในความรู้สึกปกติที่จะเริ่มต้นด้วย)
Ilmari Karonen

1
ในทางกลับกันเซิร์ฟเวอร์ NFS (โรงเรียนเก่า) อาจให้บริการโฮมไดเรกทอรีสำหรับผู้ใช้ที่ไม่ทราบชื่อตามระบบปฏิบัติการ
rackandboneman

คำตอบ:


45

ระบบหลายคนมีgetentคำสั่งไปยังรายการหรือสอบถามเนื้อหาของบริการชื่อฐานข้อมูลเช่นpasswd, group, services, protocols...

getent passwd | cut -d: -f6

จะแสดงรายการโฮมไดเรกทอรี ( ฟิลด์ตัวคั่นลำไส้ใหญ่ลำดับที่ 6 ) ของผู้ใช้ทั้งหมดในฐานข้อมูลที่สามารถระบุได้

ชื่อผู้ใช้เองอยู่ในฟิลด์แรกดังนั้นสำหรับรายชื่อผู้ใช้:

getent passwd | cut -d: -f1

(โปรดทราบว่ามันไม่ได้หมายความว่าผู้ใช้เหล่านั้นสามารถเข้าสู่ระบบหรือสร้างโฮมไดเร็กตอรี่ แต่พวกเขาเป็นที่รู้จักในระบบพวกเขาสามารถแปลเป็นรหัสผู้ใช้ได้)

สำหรับฐานข้อมูลที่ไม่สามารถระบุได้คุณสามารถลองค้นหาแต่ละ ID ผู้ใช้ที่เป็นไปได้แต่ละรายการ:

getent passwd {0..65535} | cut -d: -f1,6

(ที่นี่สมมติว่า uids หยุดที่ 65535 (บางระบบรองรับมากกว่า) และเชลล์ที่สนับสนุน zsh {x..y}การขยายรูปแบบ ) แต่คุณไม่ต้องการที่จะทำเช่นนั้นบ่อยครั้งในระบบที่ฐานข้อมูลผู้ใช้ถูกเชื่อมต่อเครือข่าย (และมีการแคชเฉพาะที่ จำกัด ) เช่น LDAP, NIS +, SQL ... ซึ่งอาจบ่งบอกถึงปริมาณเครือข่ายจำนวนมาก (และโหลดบนเซิร์ฟเวอร์ไดเรกทอรี ) เพื่อทำการค้นหาทั้งหมด

นั่นก็หมายความว่าหากมีผู้ใช้หลายคนที่แชร์ uid เดียวกันคุณจะได้รับหนึ่งรายการต่อ uid เท่านั้นดังนั้นพลาดคนอื่น ๆ

หากคุณไม่มีgetentคุณสามารถหันไปperl:

perl -le 'while (@e = getpwent) {print $e[7]}'

สำหรับgetent passwd( $e[0]สำหรับชื่อผู้ใช้) หรือ:

perl -le 'for ($i=0;$i<65536;++$i) {
  if (@e = getpwuid $i) {print $e[0] ": " $e[7]}}'

สำหรับ getent passwd {0..65535}ด้วย caveats เดียวกัน

ในเชลล์คุณสามารถใช้~userเพื่อรับโฮมไดเร็กตอรี่ของuserแต่ในเชลล์ส่วนใหญ่ที่ใช้งานได้เฉพาะกับชื่อผู้ใช้ที่ จำกัด (รายการของอักขระที่อนุญาตในชื่อผู้ใช้ที่รองรับสำหรับ~ตัวดำเนินการส่วนขยายนั้นแตกต่างจากเชลล์ไปยังเชลล์) และ กระสุนจำนวนมาก (รวมถึงbash), ใช้~$userงานไม่ได้ (คุณต้องหันไปใช้evalเมื่อชื่อของผู้ใช้ถูกเก็บในตัวแปรที่นั่น) และคุณยังคงต้องหาวิธีรับรายชื่อผู้ใช้

เชลล์บางตัวมีการสนับสนุนในตัวเพื่อรับรายการชื่อผู้ใช้นั้น

  • bash: compgen -uจะส่งคืนรายการผู้ใช้ในฐานข้อมูลที่สามารถระบุได้
  • zsh: $userdirsอาเรย์ที่เชื่อมโยงจับคู่ชื่อผู้ใช้กับโฮมไดเร็กตอรี่ (จำกัด เฉพาะฐานข้อมูลที่สามารถระบุได้, แต่ถ้าคุณทำการ~userขยายสำหรับผู้ใช้ที่อยู่ในฐานข้อมูลที่ไม่สามารถนับได้, รายการจะถูกเพิ่มเข้าไป$userdirs) ดังนั้นคุณสามารถทำได้:

    printf '%s => %s\n' "${(kv@)userdirs}"

    เพื่อแสดงรายการผู้ใช้ด้วยโฮมไดเร็กตอรี่ของพวกเขา

    ที่ทำงานเฉพาะเมื่อzshเป็น แต่แบบโต้ตอบ

  • tcsh, fishและyashสามหอยอื่น ๆ ที่สามารถดำเนินการชื่อผู้ใช้ (เช่นเมื่อเสร็จสิ้น~<Tab>การขัดแย้ง) แต่มันดูไม่เหมือนพวกเขาช่วยให้คุณได้รับรายชื่อของผู้ใช้ที่โปรแกรม


ความท้าทายสำหรับ OP จะได้รู้ว่าgetentกำลังจะไปที่นั่นหรือไม่ซึ่งฉันคิดว่าในระดับหนึ่งขึ้นอยู่กับขอบเขตของ 'เครื่องจักรอื่น ๆ ' ของพวกเขา
EightBitTony

1
@EightBitTony ฉันได้เพิ่มperlทางเลือก
Stéphane Chazelas

1
สำหรับ Mac อาจเป็นสิ่งที่เกี่ยวข้องกับ Open Directory
SilverWolf - Reinstate Monica

@eaturtle perl -le 'while (@e = getpwent) {print $e[7]}'ทำงานได้ดีบน macOS
Stéphane Chazelas

1
@FloHe เป็นชื่อผู้ใช้ ผู้ใช้ส่วนใหญ่ในระบบ Unix เป็นผู้ใช้ระบบพิเศษที่อายุการใช้งานจะทุ่มเทให้กับการใช้บริการระบบ getent passwdแสดงฐานข้อมูลผู้ใช้ ฟิลด์แรกคือชื่อผู้ใช้ฟิลด์ที่ 6 คือโฮมไดเร็กทอรีของผู้ใช้
Stéphane Chazelas

17

วิธีที่ดีกว่าในการแสดงรายการไดเรกทอรีบ้านของผู้ใช้คือการแยกวิเคราะห์ /etc/passwdและแยกมันออกมาจากที่นั่นและไม่ได้ตั้งสมมติฐานใด ๆ

และตัดสินจากความคิดเห็นที่สองของคุณคุณต้องการชื่อผู้ใช้ไม่ใช่ไดเรกทอรีบ้านของพวกเขาในกรณี/etc/passwdนี้เป็นตัวเลือกที่ดีกว่า โปรดทราบว่าเครื่อง Linux / UNIX บางเครื่องจะมีกลไกการตรวจสอบผู้ใช้อื่น ๆ ที่กำหนดค่า (เช่น LDAP) และท้ายที่สุดแบบสอบถามของคุณจะซับซ้อนกว่าที่คุณคิดไว้ก่อน แต่/etc/passwdเป็นจุดเริ่มต้นที่ดี


9
ดูเพิ่มเติมgetentที่ระบบที่รองรับ
Kusalananda

6
ใช่getentดีกว่าการแยกวิเคราะห์อยู่เสมอ/etc/passwd(ซึ่งจะกล่าวถึงข้อกังวลของ“ กลไกการพิสูจน์ตัวตนผู้ใช้อื่น ๆ ”)
สตีเฟ่น Kitt

@ Kusalananda ปัญหาเกี่ยวกับการgetentแก้ปัญหาคือมันถือว่าแหล่งข้อมูลนั้นสามารถระบุได้และไม่เพียงแค่ค้นหาค่าเฉพาะ มีรายละเอียดในStéphane Chazelas ตอบคำถามนี้แต่ฉันอยากจะเพิ่มความคิดเห็นให้ใครก็ตามที่อ่านหน้านี้
Andrew Henle

7

คำตอบสั้น ๆ :

compgen -u

คำตอบกลาง : ตั้งแต่คุณใช้bashคุณสามารถแสดงรายการสำเร็จเป็นไปได้ทั้งหมดสำหรับการใช้~ compgen -A userนั่นเป็นการใช้งานทั่วไปมันสามารถย่อcompgen -uได้ ในฐานะที่เป็นเชลล์บิวด์อินcompgenไม่มีหน้าเพจของตัวเอง แทนที่จะดูทุบตี (1)สำหรับเอกสารและอ่านส่วนที่เกี่ยวกับโปรแกรมได้แล้วเสร็จ

ทางเลือกที่ละเอียดมากขึ้น

หากคุณกำลังกังวลอย่างมากเกี่ยวกับการพกพาคุณอาจไม่ได้สามารถที่จะพึ่งพาเครื่องอื่น ๆ bashที่มี ในกรณีนี้ให้ทำดังนี้

(getent passwd ||
    dscl . -ls /Users dsAttrTypeNative:homeDirectory || 
    nidump passwd  ||
    cat /etc/passwd) 2>/dev/null  |  cut -d: -f6

คำ ตอบที่ยาวลองทุกอย่างดังนั้นมันจะทำงานบนระบบ UNIX ทุกระบบโดยไม่คำนึงว่ามันจะใช้ /etc/nsswitch.conf ที่ใหม่กว่า (ทั้ง GNU / Linux และ BSD มาพร้อมกับgetent) ไฟล์แบน UNIX ดั้งเดิมของ MacOS บริการไดเรกทอรี ( dscl) หรือแม้กระทั่งรุ่น MacOS X ที่มีธีมแมวและรุ่นเก่า NeXTSTEP ( nidump)

ความเรียบง่าย แต่คุณต้องการพกพาขนาดไหน? ยูนิกซ์มีหลายวิธีในการทำสิ่งต่าง ๆ และบางครั้งก็ง่ายกว่า หากคุณต้องเลือกอย่างใดอย่างหนึ่งฉันขอแนะนำgetent passwd | cut -d: -f6สำหรับเชลล์สคริปต์²


เชิงอรรถ¹: ฉันไม่ได้ใช้ MacOS เลยสักนิดดังนั้นถ้ามีคนยืนยันได้ว่าฉันมีซินแทกซ์ที่ถูกต้อง (และเอาท์พุทไม่ได้รวมโคโลนีจรจัดที่จะทำให้ยุ่งเหยิงcut) นั่นจะยอดเยี่ยม ขอบคุณ

เชิงอรรถ²: สิ่งที่ฉันแนะนำและสิ่งที่ฉันทำอาจแตกต่างกัน โดยส่วนตัวแล้วฉันมักจะใช้แบบดั้งเดิมcut -d: -f1 /etc/passwdที่บรรทัดคำสั่ง หลังจากการทำซ้ำหลายทศวรรษนิ้วของฉันสามารถพิมพ์ขณะที่ใจกำลังทำงานอย่างอื่นอยู่


2
เครื่อง Mac OS X ทุกเครื่องค่อนข้างรับประกันว่าจะมีการทุบตีเนื่องจากมาพร้อมกับระบบ (เช่นเดียวกับ zsh และกระสุนอื่น ๆ อีกมากมาย)
SilverWolf - Reinstate Monica

จริงพอ แต่กลับมาเมื่อฉันใช้ MacOS Apple ไม่ได้ปรับปรุงทุบตีในระยะเวลานานและมันก็เป็นสิ่งที่ดื้อดึงรุ่น 3 ที่ฉันต้องเปลี่ยนเสมอ Apple ได้รับการปรับปรุงที่ดีขึ้นเกี่ยวกับทุบตี?
hackerb9


จริงไม่ได้คิดอย่างนั้น bash รุ่นของฉัน (macOS Sierra 10.12.6) คือ 3.2.57 (:
SilverWolf - Reinstate Monica

อย่างไรก็ตามbashมีcompgen -uตั้งแต่ 2.04 เปิดตัวในปี 2000
Stéphane Chazelas

2

เกี่ยวกับls -l ~/..อะไร รายการนี้แสดงไดเรกทอรีทั้งหมดในพาเรนต์ของโฮมไดเร็กตอรี่ของคุณ


4
ใช้งานได้กับระบบที่โฮมไดเร็กตอรี่ทั้งหมดอ้างอิงในไดเรกทอรีเดียวกัน, ซึ่งไม่มากนัก (คุณอาจคิดว่า/homeเป็นเรื่องปกติในระบบลีนุกซ์, แต่จะเกิดอะไรขึ้นเมื่อคุณเรียกใช้งานเป็นroot?) รายชื่อโฮมไดเร็กตอรี่คือการผจญภัยที่เต็มไปด้วยข้อผิดพลาดหากคุณต้องการจัดการทุกกรณีที่คุณมีแนวโน้มจะเจอให้ดูคำตอบอื่น ๆ สำหรับรายละเอียด
สตีเฟ่น Kitt

7
นี่เป็นเพียงคำตอบเดียวที่ตอบปัญหาการรับรู้ของ OP โดยตรง อย่างไรก็ตามมันไม่ได้ตอบปัญหาพื้นฐานของ OP
ท่อ

1
คุณค่าในคำตอบนี้คือการเข้าใจในสิ่งที่มันขาดหายไปและทำไมมันถึงไม่ดีเท่าคำตอบที่ได้รับคะแนนสูงกว่าคนอื่น
Criggie
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.