ทำไม `cp 'และ` rm` จึงดูแลไดเรกทอรีต่างกัน


10

ทำไมเครื่องมือที่ชอบcpและrmปฏิบัติต่อไดเรกทอรีแยกจากไฟล์ปกติ? พวกเขาทั้งสองต้องการให้ผู้ใช้ระบุอย่างชัดเจนว่าเธอต้องการพฤติกรรมแบบเรียกซ้ำมิฉะนั้นพวกเขาจะไม่จัดการกับไดเรกทอรีเลย

การโต้ตอบครั้งแรกของฉัน (กลับมาอีกครั้ง) กับคอมพิวเตอร์อยู่ในสภาพแวดล้อม Windows / GUI / จุดและคลิก / ลากและวาง

พฤติกรรมนี้ทำให้ฉันผิดหวังเมื่อฉันให้คำสั่งด้วย wildcard หากฉันต้องการที่จะลบทุกอย่างในไดเรกทอรี ( *) ยกเว้นsubdirs ไม่ว่างเปล่า ?

ฉันสามารถจินตนาการได้ว่านี่เป็นคุณลักษณะด้านความปลอดภัยบางอย่างที่จะป้องกันไม่ให้ผู้ใช้ยิงตัวเองด้วยการเดินเท้า แต่สิ่งนี้ขัดแย้งกับความเข้าใจของฉันเกี่ยวกับหลักการ Unix สองสามข้อ:

  • Unix มักจะไม่ปกป้องผู้ใช้จากตัวเอง มีการสันนิษฐานเสมอว่าผู้ใช้รู้ว่าเธอกำลังทำอะไรอยู่
  • สำหรับ Unix ทุกอย่างเป็นไฟล์ ไดเรกทอรีไม่ใช่ไฟล์อื่นใช่หรือไม่ ทำไมพวกเขาถึงได้รับการปฏิบัติต่างกัน?

คำถามของฉัน:

  • พฤติกรรมนี้เกิดจากข้อ จำกัด ทางเทคนิคหรือเป็นตัวเลือกโดยเจตนาหรือไม่?

และในกรณีหลัง

  • มีเรื่องราวทางประวัติศาสตร์เกี่ยวกับเหตุผลที่กระตุ้นตัวเลือกนี้หรือไม่?

สำหรับrmอย่างน้อยถ้าคุณต้องการที่จะไม่สนใจความแตกต่างระหว่างไฟล์และไดเรกทอรีที่คุณสามารถใส่ในของคุณไฟล์:~/.bashrc alias rm='rm -r'
BenjiWiebe

1
ดูคำถามที่แตกต่าง แต่เกี่ยวข้องกันunix.stackexchange.com/questions/46066/…
derobert

1
คุณไม่สามารถเปรียบเทียบ cp และ rm กับตัวจัดการไฟล์ของ windows เริ่ม cmd.exe แล้วลองคัดลอกและลบและเปรียบเทียบลักษณะการทำงาน
ott--

คำตอบ:


11

Derobert's เหตุใดโปรแกรม unix mv จึงไม่ต้องการตัวเลือก -R (เรียกซ้ำ) สำหรับไดเรกทอรี แต่ cp ไม่ต้องการมัน? โดยทั่วไปตอบคำถามของคุณ: การคัดลอกหรือลบไฟล์ปกติแตกต่างจากการดำเนินการเดียวกันกับไดเรกทอรีเพราะสำหรับไดเรกทอรีที่คุณต้องประมวลผลไฟล์ทั้งหมดที่อยู่ในนั้น ดังนั้นการดำเนินการจะแตกต่างกันโดยพื้นฐาน

สิ่งที่ควรสังเกตอีกอย่างก็คือมียูทิลิตี้พิเศษrmdirที่สามารถทำงานกับไดเรกทอรีที่ว่างเปล่าได้เท่านั้น หากไม่มีการตรวจสอบข้อเท็จจริงสิ่งนี้นำไปสู่การสรุปว่าในขั้นต้นอาจจะrmสามารถลบไดเรกทอรีที่ไม่ใช่ไดเรกทอรีและลบลึกได้โดยการเรียกซ้ำrmไปยังไดเรกทอรีที่ว่างเปล่าแล้วจึงrmdirลบออก


rmdirยังเป็นชื่อของการเรียกของระบบที่ใช้เพื่อลบไดเรกทอรี ไดเรกทอรีจะต้องว่างเปล่าสำหรับการเรียกใช้ระบบและยูทิลิตี้ที่มีชื่อเดียวกันคือ "front-end" ซึ่งคล้ายกับunlinkคำสั่งและยูทิลิตี้
jordanm

แน่นอน - นั่นคือสิ่งที่ทำให้ฉันเชื่อว่าเดิมrmอาจไม่สามารถลบไดเรกทอรีเลย (เพราะอรรถประโยชน์บรรทัดคำสั่งมักจะล้อมรอบ syscalls ง่าย ๆ )
peterph

ชื่อคำถามของฉันอาจทำให้เข้าใจผิดคิดว่าฉันถามเกี่ยวกับรายละเอียดทางเทคนิค ฉันถูกถามว่ามันเป็นทางเลือกโดยเจตนาหรือไม่ ฉันสงสัยว่าฉันเป็นคนเดียวที่จะคิดว่าจากมุมมองของผู้ใช้ปลายทางพฤติกรรมนี้จะไม่สอดคล้องกัน ฉันยอมรับคำตอบของคุณเพราะมันตอบคำถามของฉันทางอ้อม: ข้อ จำกัด ทางเทคนิคใน Unix internals (ระดับ syscall) ดูเหมือนจะเป็นจุดเริ่มต้นของพฤติกรรมนี้และมรดกอาจทำให้เราไม่สามารถทำอย่างอื่นได้ในวันนี้ "การห่อหุ้มรอบ ๆ ตึกระฟ้า" ไม่ควรที่จะทำให้เรามีพฤติกรรมที่ฉลาดกว่าใช่มั้ย
rahmu

2
จากมุมมองผู้ใช้ปลายทางดูเหมือนว่าแปลกจริง ๆ แต่คุณถามถึงเหตุผลจริงๆ :) ส่วนที่ห่อหุ้ม - ทั้งหมดขึ้นอยู่กับว่า "เรียบง่าย" มันเป็นอย่างไร (และสิ่งที่คุณยังต้องการเรียกว่า "ง่าย") โมเดิร์นrmแน่นอนไม่ได้เป็นเพียง wrapper ง่าย (มันสามารถลบไฟล์ mroe ในครั้งเดียวและไดเรกทอรีเช่นกัน) หากคุณไม่ต้องการให้มันเป็น-rตัวเลือกให้ใช้ฟังก์ชันการสร้างสมนามของเชลล์หรือสร้าง wrapper ของคุณเองที่จะวางไว้ (ซึ่งจะช้ากว่า แต่เป็นอิสระจากเชลล์ที่คุณใช้)
peterph

2

ในบางรสชาติของ UNIX man page ของ rm ระบุว่าเป็นคำสั่งเพื่อยกเลิกการลิงก์ไฟล์
ใน UNIX ไฟล์เป็นวัตถุในระบบไฟล์ที่เรียกว่า Inodes โดยไม่มีชื่อหรือที่ตั้งนอกเหนือจาก ID ในระบบไฟล์ ชื่อของพวกเขาคือการอ้างอิงถึงพวกเขาในไดเรกทอรีต่าง ๆ ซึ่งเป็นประเภทของไฟล์ที่มีการจัดทำดัชนีไฟล์ (หรือไดเรกทอรีเนื่องจากพวกเขาเป็นไฟล์) ที่ระบุไว้ในนั้น
เมื่อยกเลิกการเชื่อมโยงไฟล์จำนวนการอ้างอิงของไฟล์จะลดลงและเมื่อถึงระดับ 0 มันจะถูกลบทิ้งเนื่องจากระบบไฟล์ถูกทำเครื่องหมายว่าว่างโดยระบบไฟล์

หากคุณมีความสามารถในการ rm ไดเรกทอรีโดยไม่ต้องยกเลิกการเชื่อมโยงไฟล์ภายในมันก่อนคุณจะไปถึงจุดที่คุณมี inodes ที่อ้างอิงในระบบไฟล์ของคุณ แต่ไม่สามารถเข้าถึงได้ด้วยวิธีปกติ
เนื่องจากมีการอ้างอิงถึงพวกเขาตามจำนวนการอ้างอิงพวกเขาจะไม่ถูกทำเครื่องหมายว่าถูกลบและกลายเป็นไฟล์ที่สูญหาย
สิ่งนี้จะมีความซับซ้อนมากยิ่งขึ้นเมื่อไฟล์ "" ที่หายไปนั้นเป็นไดเรกทอรีและทำให้จำนวนที่เก็บข้อมูลที่สูญหายในระบบไฟล์เพิ่มขึ้น

ดังนั้น rm -r จึงถูกเพิ่มเข้ามาเพื่อเพิ่มความสะดวกในการใช้ชีวิตของผู้ใช้ UNIX ด้วยค่าใช้จ่ายของ "UNIX spirit" เนื่องจากมีความซับซ้อนมากกว่ายูทิลิตี้ UNIX แบบดั้งเดิมเนื่องจากมันลดระดับลงไปยังไดเรกทอรีและลบไฟล์ภายใน

นอกจากนี้ในช่วงต้นของ UNIX ระบบไม่ได้มีหน่วยความจำจำนวนมากและการแมปโครงสร้างแบบเรียกซ้ำของไดเรกทอรีมีโทษประสิทธิภาพและบางครั้งก็เป็นไปไม่ได้ที่จะไม่แยกงาน

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

สำหรับ tl; dr ฝูงชน:
ไดเรกทอรีใน UNIX เป็นไฟล์ชนิดหนึ่ง, เป็นเรื่องจริง, แต่เนื่องจากข้อมูลภายในนั้นได้รับการปฏิบัติแตกต่างจากระบบ, เนื่องจากเป็นข้อมูลเมตาของระบบไฟล์, คำสั่งที่จัดการไฟล์ไม่สามารถทำงานบนไดเรคทอรี เปลี่ยนพฤติกรรมของพวกเขาในการจัดการข้อมูลเมตาที่ต้องพึ่งพาเช่นกัน

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