ลบไฟล์อย่างมีประสิทธิภาพจากไฟล์. tgz ขนาดใหญ่


14

สมมติว่าฉันมีไฟล์ tar-ball ที่ถูกบีบอัด gzip tarArchive.tgz (+100 ไฟล์รวมเป็น + 5gb)

อะไรจะเป็นวิธีที่เร็วที่สุดในการลบรายการทั้งหมดที่ตรงกับรูปแบบชื่อไฟล์ที่กำหนดเช่นคำนำหน้า * .jpg จากนั้นเก็บซากไว้ใน gzip: ed tar-ball อีกครั้ง

การแทนที่ที่เก็บถาวรเก่าหรือการสร้างที่เก็บใหม่นั้นไม่มีความสำคัญใด ๆ ที่เร็วที่สุด


คำตอบ:


14

ด้วย GNU tarคุณสามารถทำได้:

pigz -d < file.tgz |
  tar --delete --wildcards -f - '*/prefix*.jpg' |
  pigz > newfile.tgz

ด้วยbsdtar:

pigz -d < file.tgz |
  bsdtar -cf - --exclude='*/prefix*.jpg' @- |
  pigz > newfile.tgz

( pigzเป็นเวอร์ชันแบบมัลติเธรดgzip)

คุณสามารถเขียนทับไฟล์ทับได้เช่น:

{ pigz -d < file.tgz |
    tar --delete --wildcards -f - '*/prefix*.jpg' |
    pigz &&
    perl -e 'truncate STDOUT, tell STDOUT'
} 1<> file.tgz

แต่มันค่อนข้างมีความเสี่ยงโดยเฉพาะอย่างยิ่งหากผลลัพธ์ถูกบีบอัดน้อยกว่าไฟล์ต้นฉบับ (ในกรณีนี้ไฟล์ที่สองpigzอาจจบลงด้วยการเขียนทับพื้นที่ของไฟล์ซึ่งไฟล์แรกยังไม่ได้อ่าน)


ขอบคุณสำหรับคำตอบ upvoted จะใช้มาตรฐานในสัปดาห์หน้าเพื่อดูว่าอันไหนที่ทำงานได้ดีขึ้นสำหรับการจัดเก็บและระบบของฉันและยอมรับว่า
Aksel Willgert

8

อย่าลดวิธีง่ายๆ: อาจเร็วพอสำหรับวัตถุประสงค์ของคุณ กับ avfsเพื่อเข้าถึงการเก็บถาวรเป็นไดเรกทอรี:

cd ~/.avfs/path/to/original.tar.gz\#
pax -w -s '/^.*\.jpg$//' | gzip >/path/to/filtered.tar.gz        # POSIX
tar -czf /path/to/filtered.tar.gz -s '/^.*\.jpg$//' .            # BSD
tar -czf /path/to/filtered.tar.gz --transform '/^.*\.jpg$//' .   # GNU

ด้วยเครื่องมือแบบดั้งเดิมให้แยกไฟล์ออกก่อนยกเว้น.jpgไฟล์จากนั้นสร้างไฟล์เก็บถาวรใหม่

mkdir tmpdir && cd tmpdir
<original.tar.gz gzip -d | pax -r -pe -s '/^.*\.jpg$//'
pax -w . | gzip >filtered.tar.gz
cd .. && rm -rf tmpdir

หากน้ำมันดินของคุณมี --exclude :

mkdir tmpdir && cd tmpdir
tar -xzf original.tar.gz --exclude='*.jpg'
tar -czf filtered.tar.gz .
cd .. && rm -rf tmpdir

อย่างไรก็ตามนี่อาจทำให้ไฟล์เป็นเจ้าของและโหมดหากคุณไม่เรียกใช้ในฐานะรูท เพื่อผลลัพธ์ที่ดีที่สุดให้ใช้ไดเร็กทอรีชั่วคราวบนระบบไฟล์อย่างรวดเร็ว - tmpfs หากคุณมีขนาดใหญ่พอ

การสนับสนุนสำหรับผู้จัดเก็บเพื่อทำหน้าที่ส่งผ่าน (เช่นอ่านไฟล์เก็บถาวรและเขียนไฟล์เก็บถาวร) มีแนวโน้มที่จะถูก จำกัด tar ของ GNU สามารถลบสมาชิกออกจากไฟล์เก็บถาวรด้วย--deleteตัวเลือกการดำเนินการ (“ --deleteตัวเลือกนั้นได้รับรายงานว่าทำงานอย่างถูกต้องเมื่อtarทำหน้าที่เป็นตัวกรองจากstdinถึงstdout ”) และนั่นอาจเป็นตัวเลือกที่ดีที่สุดของคุณ

คุณสามารถสร้างตัวกรองการเก็บถาวรที่มีประสิทธิภาพในไม่กี่บรรทัดของ Python ใช้tarfileห้องสมุดสามารถอ่านและเขียนจากลำธารที่ไม่ใช่ seekable และคุณสามารถใช้โค้ดในหลามตัวกรอง, เปลี่ยนชื่อ, แก้ไข ...

#!/usr/bin/python
import re, sys, tarfile
source = tarfile.open(fileobj=sys.stdin, mode='r|*')
dest = tarfile.open(fileobj=sys.stdout, mode='w|gz')
for member in source:
    if not (member.isreg() and re.match(r'.*\.jpg\Z', member.name)):
        sys.stderr.write(member.name + '\n')
        dest.addfile(member, source.extractfile(member))
dest.close()

นอกจากนี้ยังจะรวม uid / ชื่อผู้ใช้หากรันเป็น root เว้นแต่จะทำบนเครื่องที่มี uid <=> การจับคู่ชื่อผู้ใช้เหมือนกับที่ไฟล์ tar ถูกสร้างขึ้นในตอนแรก ACLs คุณลักษณะเพิ่มเติมอาจได้รับผลกระทบเช่นกัน ด้วยtarคุณอาจต้องการเพิ่มpตัวเลือก
Stéphane Chazelas


1

ในการทำเช่นนี้คุณอาจต้องแตกไฟล์. tgz ทั้งหมดในไดเร็กตอรี่โลคัลจากนั้นลบไฟล์ที่คุณไม่ต้องการแล้วบีบอัดไฟล์. tgz อีกครั้ง

มันยาวและคุณต้องการพื้นที่ว่างบนดิสก์เพียงพอ แต่เพื่อความรู้ของฉันที่ดีที่สุดไม่มีวิธีอื่นที่จะทำ

เนื่องจากคุณมีเส้นทางเช่น/tmpdir/withalotofspaceนั้นที่มีพื้นที่ว่างเพียงพอ (ตรวจสอบโดยใช้ df -h /tmpdir/withalotofspace) คุณสามารถทำสิ่งนี้:

$ cd /tmpdir/withalotofspace
$ tar -xvfz /path/to/compressedArchive.tgz
$ find /tmpdir/withalotofspace/ -type f -iname '*.jpg' -delete
$ tar -cvzf /path/to/purgedcompressedArchive.tgz .

ดังที่คำตอบอื่น ๆ แสดงผ่านการวางท่อไม่จำเป็นต้องเก็บข้อมูลที่ไม่มีการบีบอัดลงบนดิสก์ ณ จุดใด ๆ
Tobias Kienzler

0

ฉันชอบคำตอบของ @Gilles ยกเว้นมันจะง่ายขึ้นอีก หลังจากการคลายซิปตัวอย่างเช่นgunzip foo.tgzไฟล์จะเป็นfoo.tarและไฟล์สามารถลบออกtar -f foo.tar --delete file|directoryได้ ด้านล่างเป็นตัวอย่างของการลบไดเรกทอรีออกจากไฟล์ tar

    phablet@ubuntu-phablet:~/Downloads$ tar -cvf moo.tar moo1/
    moo1/
    moo1/moo2/
    moo1/moo2/moo3/
    moo1/moo2/moo3/moo4/
    moo1/moo2/moo3/moo4/moo5/
    phablet@ubuntu-phablet:~/Downloads$ tar -tf moo.tar 
    moo1/
    moo1/moo2/
    moo1/moo2/moo3/
    moo1/moo2/moo3/moo4/
    moo1/moo2/moo3/moo4/moo5/
    phablet@ubuntu-phablet:~/Downloads$ tar -f moo.tar --delete "moo1/moo2/moo3"
    phablet@ubuntu-phablet:~/Downloads$ tar -tf moo.tar 
    moo1/
    moo1/moo2/

สามารถพบไฟล์ประเภทใดประเภทหนึ่งโดยtar -tf foo.tar|egrep -i '.jpg$'เฉพาะ

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