เหตุใดโปรแกรม unix mv จึงไม่ต้องการตัวเลือก -R (แบบเรียกซ้ำ) สำหรับไดเรกทอรี แต่ cp ไม่จำเป็นต้องใช้?


58

ฉันมักจะสับสนเมื่อจำเป็นต้องใช้cpหรือmv: "ฉันต้องการ-Rตัวเลือกเมื่อทำงานกับ dir หรือไม่" ใน GNU coreutils cpไม่ต้องการ-Rและmvไม่ทำ

ฉันไม่สามารถหาเหตุผลว่าทำไมcpต้องมี-Rตัวเลือกสำหรับการคัดลอก dirs และmvไม่ ฉันคิดว่าการที่cpdirs ไม่มี-R(แต่ทำตัวซ้ำ ๆ เหมือนมี-Rและชอบmvทำ) จะไม่ทำให้เกิดปัญหาใด ๆ ยกเว้นการทำลายนิสัยของใครบางคนในการใช้เครื่องมือ

คุณรู้คำอธิบายใด ๆ ? อาจจะมีเหตุผลมานานแล้ว?


คำถามเพิ่มเติม: เหตุใดนักพัฒนา coreutils จึงไม่ทำcpสำเนาซ้ำโดยปริยาย

คำตอบ:


45

ไดเร็กตอรี่คือ "ไฟล์" แบบพิเศษซึ่งมีรายการชื่อและหมายเลขไอโหนดจะชี้ไปที่ บางชื่ออาจเป็นไดเรกทอรีย่อย มีรายการพิเศษ..ที่ชี้ไปยังไดเร็กทอรีพาเรนต์

ดังนั้นการเปลี่ยนชื่อไฟล์จึงเป็นเรื่องง่าย: คุณแค่เปลี่ยนชื่อในรายการไดเรกทอรีไม่มีอะไรอื่นอีกแล้ว นี่ถือได้ว่าไฟล์นั้นเป็นไฟล์จริงหรือเป็น "ไฟล์" ที่ใช้ในการจัดเก็บเนื้อหาของไดเรกทอรีอื่น แท้จริงrenameตึกระฟ้าเดียวกันทำทั้งสองอย่าง

อย่างไรก็ตามการทำสำเนาเป็นการดำเนินการที่ไม่สำคัญมาก คุณสามารถคัดลอกไดเรกทอรี "ไฟล์" แต่แล้วคุณจะมีสองไดเรกทอรีที่ไฟล์เหมือนกัน หากคุณมีระบบที่อนุญาตให้เชื่อมโยงไปยังไดเรกทอรีได้ แต่เนื่องจากไม่มีระบบที่ทันสมัยอนุญาตให้อย่างน้อยก็ไม่ใช่รูทคุณต้องทำสำเนานั้นสำหรับแต่ละไดเรกทอรีย่อย คุณสามารถถามcpถึงพฤติกรรมนี้ด้วยcp -lR: -lสำหรับฮาร์ดลิงก์-Rสำหรับการสอบถามซ้ำ

แต่การทิ้งทุกอย่างที่เชื่อมโยงไว้นั้นอาจไม่ใช่สิ่งที่คุณต้องการ คุณต้องการcpคัดลอกแต่ละไฟล์แทน นั่นเป็นการดำเนินการที่ค่อนข้างแพง: แต่ละไฟล์จะต้องอ่านในหน่วยความจำและเขียนกลับไปที่ดิสก์ในตำแหน่งที่สอง จริง ๆ แล้วมันใช้เวลาหลาย syscalls เพื่อเปิดอ่านเขียนและปิดไฟล์และที่จะต้องทำซ้ำสำหรับแต่ละไฟล์

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


กำลังส่งmvจากระบบไฟล์หนึ่งไปยังอีกระบบหนึ่งเหมือนกัน "เพิ่งเปลี่ยนชื่อในรายการไดเรกทอรี"
rslnx

5
ไม่ระบบไฟล์ข้ามเหมือนกันกับการคัดลอก + ลบ (จริง ๆ แล้วrenamesyscall จะล้มเหลวสำหรับระบบไฟล์ข้าม) ไม่แน่ใจว่าในอดีตmvแม้จะรองรับการเคลื่อนไหวแบบ cross-fs
Derobert

9
ฉันสามารถบอกคุณได้จากประสบการณ์ตรงไม่ใช่การเก็งกำไรคลาสสิกที่mvไม่สนับสนุนการเคลื่อนไหวข้ามอุปกรณ์ มันเคยลองrename()และพิมพ์ข้อความแสดงข้อผิดพลาดถ้ามันล้มเหลว ฉันยังจำความรู้สึกที่น่าตกใจที่ฉันมีครั้งแรกที่ฉันใช้คุณลักษณะใหม่โดยไม่ตั้งใจ mv นี้ใช้เวลานานขนาดไหน? โอ้มันกำลังทำสำเนาซ้ำซึ่งฉันไม่ได้ตั้งใจ!
Alan Curry

5
@RuslanKhusnullin ตัวเลือกบรรทัดคำสั่งสำหรับคำสั่งทั่วไปนั้นยากที่จะเปลี่ยนแปลงเนื่องจากการใช้งานในเชลล์สคริปต์ บางคนอาจขึ้นอยู่กับพฤติกรรมปฏิเสธการคัดลอกปัจจุบันของ cp สิ่ง cross-fs อาจถูกตัดสินว่ามีโอกาสน้อยที่จะทำให้เกิดการแตก แต่อย่างที่คุณเห็นมันยังคงทำให้ Alan ประหลาดใจ
Derobert

1
@derobert มันไม่ได้ (ระบบข้ามไฟล์mvทำงานได้เฉพาะสำหรับไฟล์แต่ละไฟล์ใน BSD 4.2 บน VAX)
vonbrand

21

ให้ฉันเริ่มต้นด้วยการถามคำถามอื่น:

ความแตกต่างระหว่างcpและcp -Rคืออะไร?

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

อะไรคือความแตกต่างระหว่างmvและmv -R?

mv a bเพียงเปลี่ยนชื่อรายการเดียวในไดเรกทอรีดังนั้นหากไดเรกทอรีเป็นmved เนื้อหาจะถูกย้ายโดยอัตโนมัติเช่นกัน ในความรู้สึกที่mvแล้วให้ทรัพย์สิน recursive คือ "เปลี่ยนชื่อ" ของรายการทั้งหมดในไดเรกทอรีเปลี่ยนชื่อเช่นจากการa/1 b/1A mvที่ไม่ได้ทำเช่นนั้นซึ่งเปลี่ยนชื่อไดเรกทอรีaไปbแต่เก็บa/1ไว้a/1เป็นไม่ใช่สิ่งที่คนเข้าใจเมื่อพวกเขาอ้างถึงการย้ายบางสิ่ง: เมื่อคุณย้ายตู้เนื้อหาของตู้จะถูกย้ายเช่นกัน การดำเนินการอื่น ๆ ที่ย้ายไดเรกทอรีที่ไม่มีเนื้อหานั้นก็มีให้ใช้เช่นmkdirกัน


2
ถูกต้องฉันแค่คิดถึงcpและmvเมื่อปฏิบัติการที่พวกเขาตั้งชื่อว่า: 'ทำสำเนา' และ 'ย้าย' ดังนั้นหากฉันต้องการทำกาแฟสักถ้วยฉันคาดว่าจะมีกาแฟอีกหนึ่งถ้วยที่มีไส้เหมือนกัน (เครื่องดื่มกาแฟ) ปัญหาคือเครื่องมือไม่ได้มีไว้สำหรับ 'คนปกติ' แต่สำหรับผู้สนใจที่ตระหนักถึงโครงสร้างของดิสก์และระบบไฟล์ไม่ใช่เอนทิตีเสมือนเช่นไฟล์และ dirs ของไฟล์
rslnx

1
มีโครงสร้างที่ดีตอบสนองอย่างมีเหตุผล
Spedge

1
@RuslanKhusnullin คล้ายคลึงกาแฟของคุณทำงานสำหรับcpและmvมากเกินไป - ไม่จำเป็นต้องมีระดับของ "nerdness" ใด ๆ ที่จะเข้าใจความรู้สึกร่วมกันเพียงแค่พื้นฐาน สำเนากาแฟจริงไม่ใช่ถ้วยเปล่า - คุณต้องทำซ้ำซ้ำไม่เพียงถ้วย แต่เนื้อหาทั้งหมด (กาแฟ) ด้วย อย่างไรก็ตามเมื่อคุณย้ายกาแฟหนึ่งถ้วยคุณไม่จำเป็นต้องย้ายเนื้อหาแยกจากกัน - เนื้อหาจะย้ายไปพร้อมกับภาชนะบรรจุตามธรรมชาติ
jw013

1
@ jw013 คุณประทับใจฉันด้วย "เมื่อคุณย้ายกาแฟหนึ่งถ้วยคุณไม่ต้องย้ายเนื้อหาแยกจากกัน" มันสมเหตุสมผลจริงๆขอบคุณ แต่มันเป็นอีกชั้นหนึ่งของสิ่งที่เป็นนามธรรม ฉันคิดว่าคุณหมายถึง "ถือว่าไฟล์เป็น inode" ในขณะที่ฉันคิดว่าไฟล์เช่นลำดับไบต์โดยไม่มีข้อมูล meta
rslnx

6

โดยปกติเมื่อฉันสับสนกับตรรกะ Unix ฉันมอง Plan9 เพื่อดูว่านักประดิษฐ์ของ Unix ใช้งานเดียวกันหลายปีต่อมาโดยไม่ติดขัดกับความเข้ากันได้ย้อนหลัง

ดังนั้น Plan9 จึงเสนอcpและmvเครื่องมือในการทำงานกับไฟล์เท่านั้น

`cp f1 f2` creates f2 and copies f1's contents into it.
`mv f1 f2` renames f1 to f2 if f1 and f2 are in the same dir
           does `cp f1 f2 && rm f1` else
           can rename dirs (`mv d1 d2`) but will not move dir to another dir.

สำหรับการคัดลอก dir มีdircpที่เป็นจริง@{cd fromdir && tar c .} | @{cd todir && tar xT}(ไวยากรณ์เปลือก rc)

สำหรับการย้าย dir ฉันคิดว่ามีเพียง dircp d1 d2 && rm -r d1

ฉันคิดว่าการตัดสินใจนี้เพื่อ จำกัดcpและmvสำหรับการดำเนินการไฟล์เท่านั้น (ไม่ใช่ dirs) ทำให้การดำเนินงานของดิสก์ชัดเจนยิ่งขึ้นและการใช้tarสำหรับการคัดลอกทรีไฟล์นั้นสะดวกสบายมากสำหรับการทำความเข้าใจและการเขียนสคริปต์

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