ไดเร็กทอรี. / และ ../ คืออะไร


20

คำถามง่าย ๆ แต่ฉันไม่แน่ใจว่าจะมองหาที่ไหนและ google ไม่ตอบสนองต่อช่วงเวลาและเครื่องหมายทับ

ฉันแค่พยายามนับจำนวน # ของไฟล์และไดเรกทอรีในไดเรกทอรีปัจจุบัน (ไม่รวมโฟลเดอร์ย่อย / ไฟล์) และพยายามแยกความแตกต่างls -1 | wc -lและls | wc -lเนื่องจากดูเหมือนว่าเหมือนกัน ไซต์ที่ฉันกำลังดูพูดว่า"โปรดจำไว้ว่านี่เป็นการนับไดเรกทอรี. / และ .. / ด้วย" เกี่ยวกับคนที่มีls -1และฉันไม่แน่ใจว่านั่นหมายความว่ามันรวมถึงไดเรกทอรีก่อนหรือบางสิ่งบางอย่าง (ซึ่งฉันไม่ต้องการ) แต่ดูเหมือนจะไม่ทำเช่นนั้นจากการทดสอบ

มีคนยืนยันว่าหนึ่งในนั้นจะเพียงพอที่สุดสำหรับการนับ # ของไฟล์และไดเรกทอรีในไดเรกทอรีปัจจุบันเท่านั้น (ไม่ใช่ย่อย) และสิ่งที่พวกเขาหมายถึงโดย. / และ .. / ไดเรกทอรี?


"การเก็บไว้ในใจว่านี้ยังนับ ./ และ ../ ไดเรกทอรี" ที่เป็นธรรม (เว้นแต่เป็น typo หาและ ".." "".
vonbrand

คำตอบ:


15

ทุกไดเร็กทอรีบนระบบ Unix (และอาจเป็นระบบอื่นด้วย) มีรายการไดเร็กทอรีอย่างน้อยสองรายการ เหล่านี้คือ.(ไดเรกทอรีปัจจุบัน) และ..(ไดเรกทอรีหลัก) ในกรณีของไดเร็กทอรีรูทจุดเหล่านี้ไปยังตำแหน่งเดียวกัน แต่ด้วยไดเร็กทอรีอื่นใด ๆ นั้นจะแตกต่างกัน คุณสามารถเห็นสิ่งนี้ได้ด้วยตัวเองโดยใช้stat, pwdและcdคำสั่ง (บน Linux):

$ cd /
$ stat . .. bin sbin | grep Inode
Device: 802h/2050d      Inode: 2           Links: 27
Device: 802h/2050d      Inode: 2           Links: 27
Device: 802h/2050d      Inode: 548865      Links: 2
Device: 802h/2050d      Inode: 2670593     Links: 2
$ pwd
/
$ cd ..
$ pwd
/
$

โปรดสังเกตว่าbinและsbinแต่ละอันมีสองลิงก์ หนึ่งคือรายการไดเรกทอรีในไดเรกทอรีรากและอื่น ๆ เป็น.รายการภายในไดเรกทอรีนั้น

การใช้lsกับ pipe wc -lเป็นเคล็ดลับง่ายๆในการนับจำนวนบรรทัดในเอาต์พุต ls สมมติฐานคือแต่ละไฟล์หรือไดเร็กทอรีจะใช้หนึ่งบรรทัดในเอาต์พุต GNU ls จะทำเช่นนี้โดยอัตโนมัติเมื่อผลลัพธ์ไม่ใช่เทอร์มินัล คนอื่นอาจต้องการ-1ตัวเลือกในการเปิดใช้งานพฤติกรรมอย่างชัดเจน wc -lเพียงนับและเอาท์พุทจำนวนบรรทัด ( -l) ในอินพุตของมัน

ปัญหาด้วยวิธีที่เป็นที่อยู่ในลินุกซ์และระบบไฟล์แบบดั้งเดิมที่ใช้ชื่อลินุกซ์ไฟล์และไดเรกทอรี (พวกเขาเป็นจริงหนึ่งเดียวกันในเรื่องนี้) จะได้รับอนุญาตให้มีตัวอักษรขึ้นบรรทัดใหม่ ในการปรากฏตัวของวิธีใดวิธีหนึ่งแยกจากกัน - รายการเหล่านั้นจะถูกนับเป็นสองรายการหรือมากกว่าเมื่อในความเป็นจริงพวกเขาเป็นหนึ่ง

ตราบใดที่คุณใช้ GNU ls ไม่มีรายการไดเรกทอรีที่มีชื่อที่มีอักขระขึ้นบรรทัดใหม่และไม่มีนามแฝงแปลก ๆ สำหรับls(ตัวอย่างเช่นls -a) ทั้งคู่จะแสดงจำนวนไฟล์และไดเรกทอรีในไดเรกทอรีปัจจุบัน (หรือที่ระบุ) สำหรับคนส่วนใหญ่แล้วสิ่งนี้ดีพอ แต่มันไม่ถูกต้องในกรณีทั่วไป

หากคุณต้องการจัดการอักขระที่ผิดปกติ (ขึ้นบรรทัดใหม่) ในชื่อรายการไดเรกทอรีอย่างถูกต้องฉันขอแนะนำให้ใช้-bตัวเลือกของ ls เพื่อหลีกเลี่ยงพวกเขา ls -1bAจะพิมพ์ชื่อรายการไดเรกทอรีแต่ละรายการในบรรทัดของตัวเองยกเว้นอักขระที่ผิดปกติ (ดังนั้นแต่ละรายการไดเรกทอรีจะถูกมองเป็นหนึ่ง) รวมถึง dotfiles และ -directories แทคบนwc -lสำหรับบรรทัดคำสั่งที่สมบูรณ์ของls -1bA | wc -lซึ่งจะรายงานจำนวนไฟล์และไดเรกทอรีในไดเรกทอรีปัจจุบัน ( แต่ไม่สนใจ.และ..นั่นคือความแตกต่างระหว่าง-aและ-A) แต่ไม่ลงไปในไดเรกทอรีย่อยใด ๆ หากคุณไม่ต้องการ dotfiles ใด ๆ ที่จะนับรวมเพียงละเว้นพารามิเตอร์-Als


ทั้ง-aและ-Aรวมไฟล์ที่ซ่อนไว้ด้วยซึ่งฉันรู้ว่าฉันต้องการหลีกเลี่ยงดังนั้นอย่างมากที่สุดที่ฉันทำls -b | wc -lแต่สิ่งนี้ให้คำตอบที่ถูกต้องแก่ฉัน บรรทัดที่ฉันคัดลอกและวางเกี่ยวกับคำสั่งนี้ไม่ถูกต้องหรือไม่? หากถูกต้องฉันไม่ควรรับเอาต์พุต 8 เมื่อมี 6 ไฟล์หรือโฟลเดอร์ในไดเรกทอรีหรือไม่?
อดัม

@ อดัมใช่ว่าอาจจะทำเคล็ดลับ ("ls -b | wc -l"); คุณยังสามารถใช้ "-1" (เส้นประ + หมายเลขหนึ่ง) ซึ่งบังคับให้รายชื่อในคอลัมน์เดียวแทนที่จะเป็นทั้งหมดในบรรทัดเดียว แต่จะเกิดขึ้นเมื่อทำการไพพ์ไปยังคำสั่งอื่น ดังนั้น (imho) ฉันจะปล่อยให้มันเป็น "ls -1b | wc -l"; และไปที่ "ทดสอบ" เรียกใช้ "ls -1b" และนับจำนวนบรรทัดจากนั้นเรียกใช้ "ls -1b | wc -l" และตรวจสอบผลลัพธ์ (นั่นคือวิธีการแก้ปัญหาท่อ / test.)
ไมเคิล

@ Sarathrion คำถามที่พบบ่อยนั้นค่อนข้างทำให้เข้าใจผิด อนุสัญญาระบบไฟล์ Unix นั้นไม่ได้ "แปลก"; พวกเขาอยู่กันที่ไหนมันเป็นระบบอื่นที่จะมารับพวกเขา แต่ตกลง จากนั้นมันก็บอกว่า "คำสั่ง file ใช้หมายเลขเวทย์มนตร์เพื่อระบุ ... " ซึ่งผิด: มันใช้ฮิวริสติกมากมายเช่นกัน ไม่ค่อยน่าเชื่อถือในหนังสือของฉัน
vonbrand

@ vonbrand: ยุติธรรมพอลิงค์ถูกลบ ฉันแค่อ่านมันและมันก็ดูดี ฉันรู้ว่าฉันพบที่ดี แต่ตอนนี้จำไม่ได้ว่าอยู่ที่ไหน
Sardathrion - Reinstate Monica

1
คุณเข้าใจผิด:. และ .. เป็นสิ่งประดิษฐ์ทางประวัติศาสตร์จาก UNIX ในปี 1970 และเป็นผลมาจากช่วงเวลาที่ยังไม่มีการmkdir()เรียกใช้ระบบ ไม่ใช่ระบบไฟล์ทั้งหมดที่มีพวกเขาและพวกเขาไม่จำเป็นต้องมีแม้กระทั่งแม้กระทั่งโดย POSIX
schily

6

ในการตอบคำถามในหัวข้อ:

เมื่อไดเร็กทอรี B ถูกสร้างใน Unix จะถูกเพิ่มเป็นรายการใหม่ไปยังไดเร็กทอรี A (ไดเร็กทอรีพาเรนต์) และใน B จะเพิ่มสองรายการ: หนึ่งรายการเรียกว่า.ฮาร์ดลิงก์ไปยังตัวเองและอีกหนึ่งเรียกว่า..ฮาร์ด ลิงก์ไปที่ A.

สิ่งเหล่านี้เป็นเพียงฮาร์ดลิงก์ไปยังไดเรกทอรีที่ได้รับอนุญาต (แม้ว่า Unices เวอร์ชันเก่าบางรุ่นจะอนุญาตลิงก์ที่กำหนดเอง)

นั่นเป็นเหตุผลที่ว่าทำไมระบบไฟล์ส่วนใหญ่ ( btrfsเป็นข้อยกเว้นที่น่าสังเกต) จำนวนของlinksไดเรกทอรีนั้นบ่งบอกถึงจำนวนไดเรกทอรีย่อยที่มีอยู่ (บัญชีสำหรับ..รายการของพวกเขา)

เมื่อคุณเปลี่ยนชื่อ / ย้ายไดเรกทอรีหากอยู่ในไดเรกทอรีเดียวกัน (ภายใต้ชื่ออื่น) Aจะมีการเปลี่ยนแปลงเฉพาะรายการชื่อเท่านั้น B's .และ..ไม่ได้รับผลกระทบ แต่ถ้าคุณจะย้ายไปทำไดเรกทอรีที่แตกต่างกันแล้ว..ในBการเปลี่ยนแปลงจะ นั่นอธิบายว่าทำไมคุณสามารถเปลี่ยนชื่อไดเรกทอรีที่คุณไม่มีสิทธิ์เข้าถึงการเขียน (สมมติว่าคุณมีสิทธิ์ในการเขียนไปยังไดเรกทอรีหลัก) ตราบเท่าที่คุณไม่ย้ายไปยังไดเรกทอรีอื่น (มิฉะนั้นจำเป็นต้องเปลี่ยน..รายการป้องกัน คุณจากการย้ายมัน)

ระวังแม้ว่า: /a/b/../cอาจไม่เหมือนกัน/a/cเพราะ/a/bอาจเป็นลิงก์สัญลักษณ์ไปยังไดเรกทอรีอื่น

ข้อยกเว้นที่เกิดขึ้นเมื่อพา ธ นั้นได้cdรับคำสั่งให้เชลล์บางตัว สิ่งเหล่านั้นcdถือว่า.. มีเหตุผลโดยไม่สนใจ..รายการในไดเรกทอรี เหตุผลที่คุณมักเห็นcd -Pสคริปต์ที่เขียนอย่างถูกต้องเพื่อปิดใช้งานคุณลักษณะที่อาจทำให้เกิดความสับสนและไม่สอดคล้องกัน

ในการนับจำนวนรายการในไดเรกทอรีปัจจุบันที่ไม่รวม.และ..ด้วยbashคุณสามารถทำสิ่งต่อไปนี้

shopt -s nullglob dotglob
set -- *
echo "$#"

ด้วย zsh:

f=(*(ND))
echo $#f

portably:

find . ! -name . -prune -print | grep -c /

ฉันสับสนเล็กน้อย ทั้งสามรายการที่คุณอยู่ในรายการเพิ่มหนึ่งรายการเข้ากับการนับจริง เช่นถ้าฉันมี 6 ไฟล์หรือโฟลเดอร์ในไดเรกทอรีพวกเขาออก 7 ไม่ใช่ 6 สำหรับฉันดูเหมือนว่าls | wc -lเป็นคนเดียวที่ไม่รวม.และ..
Adam

1
@Adam lsไม่แสดงรายการไฟล์ที่ซ่อนอยู่ คุณต้องls -Aได้รับเช่นเดียวกับที่ หากคุณไม่ต้องการที่จะนับไฟล์ที่ซ่อนไว้จะปิดdotglob(สำหรับทุบตี) หรือD(สำหรับ zsh) หรือเพิ่ม! -name '.*'ก่อนสำหรับ-print find
Stéphane Chazelas

ใช่ฉันเพิ่งสังเกตเห็นนี้หลังจากรายการไฟล์จริง คุณรู้หรือไม่ว่าทำไมls | wc -lยังให้คำตอบที่ถูกต้องแก่ฉันและยกเว้นไฟล์ที่ซ่อนอยู่.& ..?
อดัม

1
อดัมในไดเรกทอรีของคุณคุณมี., ..และไฟล์อื่นที่มีชื่อขึ้นต้นด้วย.ที่ไม่ได้อยู่โดยคำสั่ง ls ls -Aแต่จะโดย ดังนั้นls | wc -lอย่าให้คำตอบที่ถูกต้องเพราะมันไม่นับไฟล์ที่ซ่อนอยู่
Stéphane Chazelas

1
ใช่.และถูกซ่อนไฟล์ตั้งแต่พวกเขาเริ่มต้นด้วย.. .มีแม้กระทั่งตำนานที่อธิบายว่า dotfiles จะถูกซ่อนไว้โดยบังเอิญขณะที่การดำเนินการในช่วงต้นของlsก็หมายความว่าจะไม่รวมเท่านั้น.และ..แต่ก็มีข้อผิดพลาดที่เกิดขึ้นจะไม่รวมไฟล์ใด ๆ .ที่เริ่มต้นด้วย ls | wc -lไม่ทำงานหากชื่อไฟล์มีอักขระขึ้นบรรทัดใหม่
Stéphane Chazelas

1

ฉันไม่ใช่ผู้เชี่ยวชาญ Linux ที่ยอดเยี่ยม แต่ฉันรู้จัก Linux (เคยเป็นผู้ดูแลระบบเมื่อ 16 ปีที่แล้วบน Slackware :) เวลาเก่าดี

ไดเรกทอรี. / และ .. / ง่ายๆได้: เป็นไดเรกทอรีปัจจุบัน .. เป็นไดเรกทอรีก่อนหน้า (ในแผนผังของ pwd -local directory command-

หากนับพวกเขาฉันคิดว่าพวกเขาเพิ่ม 2 ไปยังรายชื่อทั้งหมดไม่ไปซ้ำและนับไดเรกทอรีด้านล่างไดเรกทอรีปัจจุบันและนับไดเรกทอรีปัจจุบันอีกครั้ง (.) :))

โดยพื้นฐานแล้วฉันคิดว่ามันเพิ่มค่า 2 เพื่อนับ (ไฟล์) ในไดเรกทอรีปัจจุบัน

ทุกคนแก้ไขฉันถ้าฉันผิด

ฉันเพิ่งโพสต์เพื่อช่วยและเห็นว่าไม่มีใครตอบคำถามนี้ที่นี่พวกเขาอาจไม่ว่าง แต่เพียงแค่ทดสอบและดูว่าคุณมี 10 ไฟล์และรับจำนวน 12 แล้วใช่ไหม


ใช่เอเดรียถูกต้อง:. เป็น dir ปัจจุบันและ .. เป็นไดเรกทอรีด้านบนทันทีในลำดับชั้น
schaiba

.. ไม่ได้อ้างถึงไดเรกทอรีก่อนหน้าในทรีเสมอ: ใน "/" .. อ้างถึงไดเรกทอรีปัจจุบันด้วยเช่นกัน
Bonsi Scott

เพราะคุณอาจจะอยู่ใน / รากของระบบไฟล์หรือไม่
Adrian Tanase

ถ้ามันเพิ่มสองไฟล์ลงใน # ของไฟล์ในไดเรกทอรีทำไมฉันถึงได้คำตอบที่ถูกต้องเมื่อทำการทดสอบใน terminal บน osx? เช่นไดเรกทอรีที่มี 6 ไฟล์หรือโฟลเดอร์จะส่งออก 6 ไม่ใช่ 8 เมื่อฉันls | wc -1
Adam

ฉันรู้ว่าเป็นเพราะพวกเขารวมถึงไฟล์ที่ซ่อนอยู่ (เช่น. ds_store) แต่ฉันยังไม่เห็นวิธีการls | wc -lรวม.และ..เมื่อฉันได้รับคำตอบที่ถูกต้องตรงข้ามกับคำตอบที่ถูกต้อง + 2
Adam
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.