จะทำการ mv โฟลเดอร์ใน Linux ได้อย่างไร?


12

ฉันใช้ CentOS 5.5 และต้องการย้ายโฟลเดอร์จำนวนมากภายในโวลุ่มเดียวโดยคงไว้ที่mtimeเดิม

ทางออกที่ดีที่สุดที่ฉันเจอคือ:

cp -p -r source/data target/
rm -rf source/data

ด้วยข้อมูลมากกว่า 1TB ในการแบ่งปัน NFS การคัดลอกจะใช้เวลาตลอดไป ฉันไม่ต้องการคัดลอก ฉันต้องการย้ายทันที

เมื่อตอนที่ผมย้ายโฟลเดอร์โดยใช้mv source/data target/ที่mtimeของโฟลเดอร์ (ไม่ใช่ไฟล์) ได้รับการตั้งค่าให้เวลาปัจจุบัน นี่เป็นเพราะเนื้อหาของโฟลเดอร์ที่ฉันกำลังเคลื่อนย้ายได้รับการแก้ไขโดยการดำเนินการนี้ ( ..รายการชี้ไปที่ไอโหนดอื่น)

ฉันมากับเชลล์สคริปต์ต่อไปนี้ฉันเรียกว่าmv_preserve_mtime.sh:

#!/bin/bash
# Moves source folder to target folder. 
# You are responsible for making sure the target does not exist, otherwise this blows up
export timestamp=`stat -c %y $1`
mv "$1" "$2"
touch --date="${timestamp}" $2

ก็ไม่ได้ผลเช่นกัน โฟลเดอร์ได้mtimeรับการกู้คืน แต่โฟลเดอร์ทั้งหมดภายในโฟลเดอร์ที่ฉันย้าย (เฉพาะระดับ 1 ระดับลึก) เท่านั้นที่จะได้รับการmtimeรีเซ็ตด้วยเหตุผลที่ฉันไม่เข้าใจ

ไม่มีใครมีวิธีที่เหมาะสมมีประสิทธิภาพและถูกต้องหรือไม่


ฉันสงสัยว่าทำไมความพยายามของคุณถึงtouchไม่ทำงาน มันเป็นmvขั้นตอนหรือtouchขั้นตอนที่เปลี่ยน mtime ของไดเรกทอรีย่อยหรือไม่? ระบบปฏิบัติการใดที่อยู่บนเซิร์ฟเวอร์ NFS และ (ถ้าคุณรู้) ระบบไฟล์ประเภทใด
Gilles 'หยุดชั่วร้าย'

@Gilles: ฉันไม่รู้ว่าทำไมมันเกิดขึ้น มันเป็นmvขั้นตอนที่ทำให้เกิดปัญหา เซิร์ฟเวอร์ NFS เป็นที่เก็บข้อมูล NetApp จริง ๆ ฉันไม่รู้อะไรเลยเกี่ยวกับการใช้งานภายใน
Roman Zenka

1
ขอบคุณ ฉันสงสัยว่ามันเป็นเรื่องแปลกของเน็ตแอพ มิฉะนั้นtouchควรทำงาน touch -r "$1" reference.tmp; mv -- "$1" "$2"; touch -r reference.tmp -- "$2"; rm reference.tmpโดยวิธีการที่เป็นวิธีแบบพกพามากขึ้นจะ
Gilles 'หยุดชั่วร้าย'

@Gilles: น่าสนใจมากไม่รู้statว่าไม่ได้พกพา
Roman Zenka

คำตอบ:


15

POSIX mvไม่มีตัวเลือกใด ๆ ที่จะขอการเก็บรักษาแบบอะไมม์ / mtime แต่เนื่องจากการดำเนินการเป็นแบบโลคัลในโวลุ่มเดียวกันคุณสามารถขอcpให้ใช้ฮาร์ดลิงก์แทนการคัดลอกข้อมูลของไฟล์ปกติโดยใช้-lตัวเลือก:

cp -p -r -l source/date target/
rm -rf source/data

เนื่องจากมีเพียงไดเรกทอรีและการอ้างอิงไฟล์เท่านั้นที่จะถูกคัดลอกจึงควรทำงานได้เร็วขึ้นมาก:

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับฮาร์ดลิงก์คุณสามารถปรึกษาหน้า Wikipedia ที่เกี่ยวข้อง

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


mtime นั้นซับซ้อนกว่านั้น เฉพาะไดเรกทอรีแม่และไดเรกทอรีโดยตรงภายใต้มันมีการเปลี่ยนแปลง mtime ไดเรกทอรีอื่นทั้งหมดยังคงเหมือนเดิม หนึ่งคาดว่าจะเปลี่ยนทุกไดเรกทอรีเดียวหรือเพียงผู้ปกครอง
Roman Zenka

1
อันที่จริงแล้วมันสมเหตุสมผล: 1) ไดเรกทอรีหลักมี mtime ที่ดีเพราะมันถูกกำหนดอย่างชัดเจนโดยการสัมผัส 2) รายการไดเรกทอรีที่สร้างใหม่ด้วยไดเรกทอรีหลัก แต่ mtime ของพวกเขาไม่ได้ถูกกู้คืนด้วยตนเอง (โครงสร้างไดเรกทอรี Unix และรูปแบบ inode) 3) โครงสร้างของส่วนที่เหลือไม่ได้เปลี่ยนแปลงจริง ๆ เนื่องจากเรายังคงอยู่ในปริมาณเดียวกัน: นั่นเป็นสาเหตุที่mvไม่มีตัวเลือก "แบบเรียกซ้ำ" การลงไปสู่ไดเรกทอรีย่อยจะทำได้ก็ต่อเมื่อจำเป็นต้องใช้การคัดลอกจริง
ยูเรก้า

@Eureka: คำอธิบายที่ดี แต่ทำไมมันถึงทำแบบนี้? ถ้าฉันจะนำไปใช้mvในไดเรกทอรีdataฉันก็จะเปลี่ยน..ในdataเนื้อหาของและปรับเปลี่ยนsourceและtargetไดเรกทอรีเพื่อรายการรายการที่ถูกย้าย ไม่จำเป็นต้องแตะไดเรกทอรีอื่น
Roman Zenka

1
@Roman Zenka หลังจากการค้นหาบางอย่างพฤติกรรมนี้ดูเหมือนจะถูกระบุอย่างหลวม ๆ ระหว่าง Unices และระบบไฟล์และขึ้นอยู่กับrenameการนำ syscall พื้นฐานไปใช้จำนวนมากโดยเคอร์เนลและระบบไฟล์ที่ใช้แล้ว NFS จะเพิ่มการแชร์ให้กับปัญหา มีตัวชี้บางตัวที่อ้างอิงถึงความไม่สอดคล้องกันนี้: patchwork.ozlabs.org/patch/25833 bugs.opensolaris.org/bugdatabase/ …
Eureka

@ ยูเรก้า: ฉันคิดว่ามันยากมากที่จะเชื่อว่าบางสิ่งบางอย่างที่ฉันคิดว่าพื้นฐานอาจเป็นระเบียบได้ เกือบจะเป็นปี 2011 ขอบคุณสำหรับทรัพยากรเหล่านั้น!
Roman Zenka

4

วิธีแก้ไขอื่นอาจ:

rsync -a - ลบซอร์สไฟล์ / เป้าหมายข้อมูล /


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