ฉันจะบีบอัดไฟล์บน Linux ได้อย่างไรโดยไม่ต้องใช้พื้นที่ดิสก์เพิ่มเติม


20

ฉันมีไดรฟ์ 100GB ที่มีไฟล์ 95GB ฉันต้องเพิ่มพื้นที่ว่างบนไดรฟ์ (และตอนนี้การถ่ายโอนไฟล์ออกจากไดรฟ์ไม่ใช่ตัวเลือก) ไฟล์จะบีบอัดได้ดีกับgzipหรือbz2อะไรก็ตาม แต่โปรแกรมเหล่านี้เขียนไฟล์บีบอัดไปยังไฟล์แยกต่างหาก ฉันมีพื้นที่ว่างไม่เพียงพอสำหรับเรื่องนี้

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


ตัวเลือกสุดท้ายที่เราใช้ในสถานที่เก่าของฉันคือการมี dir ที่ไหนสักแห่งซึ่งมีไฟล์ 1G เต็มไปด้วยขยะ จากนั้นหากคุณเหน็บแนมคุณสามารถลบบางส่วนออกเพื่อให้คุณมีพื้นที่ฉุกเฉินเล็กน้อย

คำตอบ:


13

นี่เป็นข้อพิสูจน์ของแนวคิดทุบตีซับใน แต่มันควรเริ่มต้นให้คุณ ใช้ความเสี่ยงของคุณเอง

truncate -s `gzip -c file | dd of=file conv=notrunc 2>&1 | sed -n '$ s/ .*$// p'` file
mv file file.gz

สิ่งนี้ทำงานได้โดยการไพพ์ข้อมูล gz ไปยังกระบวนการ dd ที่เขียนกลับไปยังไฟล์เดียวกัน เมื่อเสร็จสิ้นไฟล์จะถูกตัดให้มีขนาดเท่ากับเอาต์พุต gz

นี่ถือว่าบรรทัดสุดท้ายของเอาต์พุต dd ตรงกัน:

คัดลอก 4307 ไบต์ (4.3 kB), 2.5855e-05 s, 167 MB / s

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


เคล็ดลับที่ดี คุณช่วยอธิบายconv=notruncได้ไหมว่าทำไมถึงจำเป็น?
sleske

อาจจะไม่ gzip -c file | dd of=fileดูเหมือนว่าจะใช้งานได้เช่นกัน
user710307

1
ผู้คนที่เชื่อมโยงคำถามก็ลอง (และฉันก็ลองด้วย) มันไม่ทำงานโดยทั่วไป ดูเหมือนว่าจะใช้งานได้กับไฟล์ที่มีขนาดเล็กมาก - อาจเป็นเพราะ gzip จะอ่านไฟล์ขนาดเล็กลงใน RAM ก่อนที่จะบีบอัด สำหรับไฟล์ขนาดใหญ่ (ไม่กี่ MB) มันจะไม่ทำงานแม้ว่าไฟล์นั้นจะสามารถบีบอัดได้
sleske

3
อ๋อ ดังนั้นจำเป็นต้องมี Conv = notrunc
user710307

1
เป็นไปได้ไหมว่าเมื่อใดก็ตามที่โปรแกรมบีบอัด (เช่นgzip) เขียนส่วนหัวและไบต์ข้อมูลมากกว่าไบต์ข้อมูลดั้งเดิมจึงเขียนทับบางส่วนของไฟล์? ฉันเดาว่าสิ่งนี้ขึ้นอยู่กับโปรแกรมบีบอัดที่เลือก มีใครบ้างที่คิดว่าจะป้องกันไม่ให้เกิดเหตุการณ์นี้ขึ้นหรือว่าเป็นไปได้หรือไม่ (im)
Daniel Böhmer

7

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

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

# some distributions mount /dev/shm as tmpfs; replace with bzip2 if you prefer
if gzip -q9c /full/disk/somefile > /dev/shm/somefile.gz
then
    rm -f /full/disk/somefile && mv -i /dev/shm/somefile.gz /full/disk
fi

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


1
นั่นมันบ้ามากพอที่จะทำงาน
แอนดรูแลมเบิร์ต

ฉันชอบที่จะผลักซองจดหมาย
James Sneeringer

3

ไม่มีเครื่องมือที่ทำงานด้วยวิธีนี้ได้อย่างแม่นยำด้วยเหตุผลที่คุณให้ มีคนเพียงไม่กี่คนที่เต็มใจที่จะเขียนเครื่องมือที่มีพฤติกรรมเสี่ยงโดยเจตนา


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

ไม่มีวิธีที่ดีที่จะลบข้อมูลจากจุดเริ่มต้นของไฟล์บนระบบไฟล์ใด ๆ ด้วยเครื่องมือใด ๆ
Ignacio Vazquez-Abrams

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

1

คำสั่ง split และ csplit สามารถใช้เพื่อแบ่งไฟล์ขนาดใหญ่ออกเป็นส่วนเล็ก ๆ แล้วบีบอัดแต่ละไฟล์ได้ การประกอบซ้ำจะใช้เวลาค่อนข้างนาน


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