จะย้ายและสร้างโฟลเดอร์ใหม่ในเวลาเดียวกันได้อย่างไร?


9

ฉันมีโฟลเดอร์ชื่อหนึ่งstatisticsในเซิร์ฟเวอร์อูบุนตูซึ่งจัดเก็บไฟล์ข้อมูลเป็นประจำ ฉันจะเปลี่ยนชื่อstatisticsโฟลเดอร์เป็นbackup-xxในขณะที่สร้างstatisticsโฟลเดอร์ใหม่เพื่อให้สามารถจัดเก็บไฟล์ใหม่ได้อย่างไร

แฟ้มในstatisticsโฟลเดอร์ที่ถูกสร้างขึ้นโดย file_put_contentsPHP

ฉันต้องการเปลี่ยนชื่อโฟลเดอร์เนื่องจากมีไฟล์จำนวนมากในstatisticsโฟลเดอร์


ตอนแรกฉันคิดว่าคุณหมายถึง"ในเวลาเดียวกัน"ว่าการดำเนินการควรเป็น"อะตอมมิก" (เท่าที่จะทำได้)
phk

@phk ใช่มันเป็นสิ่งที่ฉันหมายถึง
Googlebot

คำศัพท์ที่ถูกต้องจะเป็น "ไดเรกทอรี" และไม่ใช่ "โฟลเดอร์" ตามวิธี
Berk Özbalcı

คำตอบ:


7
mv statistics backup-xx && mkdir statistics

สิ่งนี้จะเปลี่ยนชื่อstatisticsไดเรกทอรีที่มีอยู่เป็นbackup-xxและถ้าสำเร็จจะดำเนินการต่อเพื่อสร้างstatisticsไดเรกทอรีใหม่

สำหรับการทำงานแบบปรมาณูให้พิจารณาสร้างไดเรกทอรีstatistics-001(หรือคล้ายกันโดยอาจแทนที่001ด้วยวันที่วันนี้ในรูปแบบที่เหมาะสม) และลิงก์สัญลักษณ์ที่เรียกว่าstatistics:

mkdir statistics-001
ln -s statistics-001 statistics

เมื่อคุณต้องการ "หมุน" สิ่งนี้เพื่อให้ข้อมูลใหม่เข้าสู่ไดเรกทอรีที่สะอาดให้สร้างไดเรกทอรีก่อนจากนั้นสร้างstatisticsลิงก์ขึ้นมาใหม่:

mkdir statistics-002
ln -sf statistics-002 statistics

mv statistics-001 backup-001

วิธีนี้ใด ๆ การเขียนโปรแกรมไปยังstatisticsไดเรกทอรี (เช่นไดเรกทอรีที่จุดนี้จะเชื่อมโยงสัญลักษณ์) จะไม่1ล้มเหลวที่จะพบว่ามัน

หากคุณต้องการสิทธิ์พิเศษหรือการตั้งค่าความเป็นเจ้าของในไดเรกทอรีที่statisticsชี้ไปที่ให้ตั้งค่าเหล่านี้ก่อน (อีกครั้ง) สร้างการเชื่อมโยง

1 หรือมากกว่านั้นด้วยวิธีนี้เวลาที่โปรแกรมจะไม่มีไดเรกทอรีเป้าหมายที่ถูกต้องจะถูกย่อให้เล็กที่สุดเท่าที่จะเป็นไปได้โดยใช้เครื่องมือ Unix มาตรฐาน


1
คุณอาจต้องการchown --reference=backup-xx statistics ; chmod --reference=backup-xx statisticsตั้งค่าการเป็นเจ้าของและการอนุญาต เป็นการดีที่คุณจะทำก่อนที่จะเปลี่ยนชื่อดังนั้นmkdir new ; chown ; chmod ; mv stats backup ; mv new statsกระบวนการพิมพ์
สตีเฟ่นแฮร์ริส

@StephenHarris ใช่ในระบบที่มีการตั้งค่าสถานะเหล่านั้น
Kusalananda

แม้ว่านี่ไม่ใช่อะตอม มันใกล้กับอะตอม แต่ไม่มาก
CVN

@ MichaelKjörlingแก้ไข
Kusalananda

ln -sfไม่ใช่อะตอม มันระบุให้ยกเลิกการเชื่อมโยง symlink เก่าจากนั้นสร้างใหม่ซึ่งไม่จำเป็นต้องเป็นอะตอม แต่คุณต้องสร้าง symlink ชั่วคราวเพิ่มเติมและใช้renameฟังก์ชัน (ผ่านmvคำสั่งเป็นต้น) เพื่อแทนที่แบบเก่า ดูวิธีการของฉันที่นี่: git.musl-libc.org/cgit/musl/tree/tools/ …
R .. GitHub หยุดช่วยน้ำแข็ง

12

ไม่มีทางที่จะแทนที่ไดเรกทอรีด้วยไดเรกทอรีอื่นแบบอะตอม คุณสามารถย้ายไดเรกทอรีเก่าแล้วสร้างไดเรกทอรีใหม่:

mv statistics backup-xx
mkdir statistics

แต่สิ่งนี้จะทำให้หน้าต่างเล็ก ๆ ของเวลาที่statisticsไม่มีอยู่ นี่เป็นปัญหาหากกระบวนการบางอย่างอาจวางไฟล์ในไดเรกทอรีได้ตลอดเวลา

หากต้องการแทนที่ไดเรกทอรีอย่างมีประสิทธิภาพคุณต้องใช้ลิงก์สัญลักษณ์ สร้างไดเรกทอรีที่ชื่อมีช่วงเวลาตั้งแต่เริ่มต้น:

mkdir "statistics-$(date +%Y%m%d)"

(หรืออย่างไรก็ตามคุณต้องการเลือกแบบแผนการตั้งชื่อไดเรกทอรี) สร้างลิงก์สัญลักษณ์ที่มีชื่อคงที่ไปยังตำแหน่งปัจจุบัน:

ln -s  statistics

หากต้องการแทนที่ไดเรกทอรีให้สร้างไดเรกทอรีใหม่และลิงก์สัญลักษณ์ใหม่จากนั้นย้ายไดเรกทอรีดังกล่าวเพื่อเขียนทับลิงก์สัญลักษณ์เก่า โปรดทราบว่าทั้งธรรมดาmvในลิงก์สัญลักษณ์หรือธรรมดาln -sจะไม่ทำเช่นนี้พวกเขาจะสร้างรายการภายในไดเรกทอรีเป้าหมาย coreutils ของ GNU ln -snfไม่เหมาะสมเช่นกันเพราะจะลบ symlink ที่มีอยู่ก่อนที่จะสร้างขึ้นใหม่ซึ่งจะทำให้หน้าต่างเวลาเล็ก ๆ ในระหว่างที่ไม่มีเส้นทาง คุณสามารถใช้ coreutils ของ GNU mv -Tบนลิงก์สัญลักษณ์ใหม่ได้

new_dir="statistics-$(date +%Y%m%d)"
mkdir "$new_dir"
ln -s statistics.new
mv -Tf statistics.new statistics

busybox' ln -sfยังไม่ใช่อะตอมฉันไม่รู้การใช้งานใด ๆ
phk

1
ข้าง symk ความคิดเห็นของ phk ก็ไม่ปลอดภัย 100% เพราะกระบวนการทำงานอาจยังคงมีคำอธิบายไฟล์ไดเรกทอรีเปิด (เป้าหมาย symlink) และมันสามารถสร้างไฟล์ใหม่เพิ่มเติมในไดเรกทอรีที่เปลี่ยนชื่อ (คิดopenat()หรือ CWD) ฉันจะย้ายเนื้อหาของไดเรกทอรีไปยังไดเรกทอรีใหม่เท่านั้น ยังคงไม่ปลอดภัยเกี่ยวกับไฟล์ที่เปิด แต่ดีกว่าเล็กน้อย หากมีข้อสงสัยในการใช้งานlogrotateซึ่งควรเคารพปัญหาดังกล่าวให้ได้มากที่สุด
rudimeier

1
@phk การsymlinkเรียกระบบจะไม่เขียนทับไฟล์ที่มีอยู่ดังนั้นจึงเป็นไปไม่ได้ที่จะเปลี่ยนลิงก์สัญลักษณ์โดยตรงแบบอะตอมขออภัย การrenameเรียกของระบบจะเขียนทับไฟล์ที่มีอยู่ แต่น่ารำคาญว่าไม่มีวิธีการพกพาในเชลล์ เป็นไปได้กับ GNU coreutils ขอบคุณ-Tตัวเลือก
Gilles 'หยุดความชั่วร้าย'

3

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

ดังนั้นเพียงทำ:

mkdir backup-xx && mv statistics/* backup-xx

หากคุณต้องการรับไฟล์ที่ซ่อนอยู่ด้วยคุณสามารถทำได้:

mkdir backup-xx && mv statistics/* statistics/.* backup-xx

หรือถ้าใช้bash:

shopt -s dotglob; mkdir backup-xx && mv statistics/* statistics/.* backup-xx

วิธีนี้ไดเรกทอรีอยู่ที่นั่นเสมอ แต่คุณยังคงย้ายเนื้อหาในการดำเนินการที่ง่ายและรวดเร็ว


1

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

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