Làm cách nào để giải nén 2 triệu tệp gzip mà không lưu trữ chúng hai lần?


8

Tôi có khoảng 2 triệu (60GiB) các tệp nhỏ được nén và tôi muốn tạo một kho lưu trữ nén chứa tất cả chúng trong một phiên bản không nén. Thật không may, tôi không thể giải nén tất cả chúng và sau đó tạo tệp lưu trữ nén vì tôi chỉ có khoảng 70GiB dung lượng đĩa trống. Nói cách khác, làm thế nào tôi có thể làm tương đương tar --file-filter="zcat" zcf file.tar.gz directorynếu chuyển đổi dòng lệnh như --file-filterkhông tồn tại trong GNU tar?


Bạn có một máy đa bộ xử lý?
Anthon

1
@Anthon: không phải trên máy này, nhưng đối với những độc giả tương lai, chúng tôi có thể cho rằng có.
d33tah

Khi bạn phải giải nén, có một cái gì đó đạt được ở đó. Bất kỳ lý do cụ thể tại sao để sử dụng gzip? Kết hợp và nén sẽ tiết kiệm không gian, nhưng bạn sẽ thu được nhiều hơn nếu bạn nén vào xztệp tar -ed. Đó có phải là một lựa chọn không?
Anthon

Bất kỳ chương trình nén sẽ làm. Nếu tôi có thể tạo một tệp tar của các tệp được giải nén nhưng không được lưu trữ, tôi có thể chuyển nó sang bất kỳ chương trình nào khác.
d33tah

Câu trả lời:


6

Một tùy chọn có thể được sử dụng avfs(ở đây giả sử hệ thống GNU):

mkdir ~/AVFS &&
avfsd ~/AVFS &&
cd ~/AVFS/where/your/gz/files/are/ &&
find . -name '*.gz' -type f -printf '%p#\0' |
  tar --null -T - --transform='s/.gz#$//' -cf - | pigz > /dest/file.tar.gz

3

Hãy lưu ý rằng điều này rất mong manh khi nói đến tên tệp khó chịu.

dir_with_small_files=/home/john/files
tmpdir=/tmp/ul/dst
tarfile=/tmp/ul.tar
mkfifo "${tarfile}"

gzip <"${tarfile}" >"${tarfile}.gz" &

find "$dir_with_small_files" -type f | \
while read src; do
    dstdir="${tmpdir}/$(dirname $src)"
    dst="$(basename $src .gz)"
    mkdir -p "$dstdir"
    gunzip <"$src" >"${dstdir}/${dst}"
    # rm "$src" # uncomment to remove the original files
    echo "${dstdir}/${dst}"
done | \
cpio --create --format=ustar -v --quiet 2>&1 >"${tarfile}" | \
while read x; do
    rm "$x"
done

# clean-up
rm "$tarfile"
rm -r "$tmpdir"

Các tập tin tạm thời không được nén $tmpdir, được chuyển đến cpiongay sau khi chúng được thêm vào kho lưu trữ, đã bị xóa.


1
Ngoài ra, nếu bạn có nhiều luồng, tôi khuyên bạn nên sử dụng pigzthay thế cho gzip :)
Christopher Stanley

2

Đây là những gì tôi đã thử cho đến nay - nó dường như hoạt động, nhưng rất chậm, ngay cả với PyPy:

#!/usr/bin/python

import tarfile
import os
import gzip
import sys
import cStringIO

tar = tarfile.open("/dev/stdout", "w|")
for name in sys.stdin:
    name = name[:-1]  # remove the trailing newline
    try:
        f = gzip.open(name)
        b = f.read()
        f.close()
    except IOError:
        f = open(name)
        b = f.read()
        f.close()
    # the [2:] there is to remove ./ from "find" output
    ti = tarfile.TarInfo(name[2:])
    ti.size = len(b)
    io = cStringIO.StringIO(b)
    tar.addfile(ti, io)
tar.close()

Sử dụng: find . | script.py | gzip > file.tar.gz


Việc giải nén và đặc biệt là giải nén trên một đĩa gần đầy, sẽ bị chậm, không có vấn đề gì.
Cristian Ciupitu

@CristianCiupitu: Tôi đã đo mà không có |gzipvà tập tin không nén về cơ bản không chạm vào ổ cứng, vì vậy IMHO không nên chậm.
d33tah

1
De và Recompressing được thực hiện bằng mã C được tối ưu hóa trong CPython. Có thể có bộ đệm liên quan khiến đĩa không được chạm vào.
Anthon

1
tìm thấy . -exec mèo \ {\} \; > / dev / null sẽ cung cấp giới hạn thấp hơn về lượng thời gian mà thao tác này có thể mất. Tôi sẽ tưởng tượng rằng một phần của vấn đề của bạn là việc tạo ra một loạt các đối tượng trăn lớn chứa các tệp của bạn ở cả hai dạng nén và không nén và sau đó để cho trình thu gom rác tự dọn sạch. xem tại đây: stackoverflow.com/questions/6115066/
Mạnh

Bạn có thể có thể lưu một số bộ nhớ bằng cách tìm ra kích thước không nén và chuyển đến tartệp gzip giống như đối tượng.
Cristian Ciupitu
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.