Làm cách nào tôi có thể nén một tệp trên Linux tại chỗ mà không cần sử dụng thêm dung lượng đĩa?


20

Tôi đã có một ổ đĩa 100 GB có tệp 95 GB. Tôi cần giải phóng một số dung lượng trên ổ đĩa (và ngay bây giờ việc chuyển tệp ra khỏi ổ đĩa không phải là một tùy chọn). Tệp sẽ nén tốt với gziphoặc bz2bất cứ thứ gì, nhưng tất cả các chương trình này ghi tệp nén vào một tệp riêng. Tôi không có đủ không gian trống cho việc này.

Có cách nào sử dụng các công cụ nén tiêu chuẩn hoặc các tiện ích Unix khác để nén tệp mà không sử dụng bất kỳ không gian đĩa bổ sung nào (hoặc ít nhất là một lượng không gian đĩa bổ sung tối thiểu) không? Tôi đang hình dung một cái gì đó nén một phần của tệp tại một thời điểm và ghi kết quả trực tiếp lên tệp. Tôi nhận ra điều này sẽ rất rủi ro, vì tệp sẽ bị hỏng nếu quá trình nén bị gián đoạn, nhưng tôi không nghĩ mình có lựa chọn nào khác.


Một lựa chọn cuối cùng mà chúng tôi thường sử dụng ở nơi cũ của tôi là có một thư mục ở đâu đó chứa toàn bộ các tệp 1G chứa đầy rác. Sau đó, nếu bạn rơi vào tình trạng khó khăn, bạn có thể loại bỏ một vài trong số chúng để cung cấp cho bạn một chút không gian khẩn cấp.

Câu trả lời:


13

Đây là một bằng chứng về khái niệm bash one-liner, nhưng nó sẽ giúp bạn bắt đầu. Sử dụng có nguy cơ của riêng bạn.

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

Điều này hoạt động bằng cách chuyển dữ liệu gz vào một quy trình dd ghi lại vào cùng một tệp. Sau khi hoàn thành, tập tin được cắt theo kích thước của đầu ra gz.

Điều này giả định rằng dòng cuối cùng của đầu ra của dd khớp với:

4307 byte (4,3 kB) được sao chép, 2,5855e-05 s, 167 MB / s

Trong đó trường đầu tiên là một số nguyên byte được viết. Đây là kích thước tập tin sẽ cần phải được cắt ngắn. Tôi không chắc chắn 100% rằng định dạng đầu ra luôn giống nhau.


Thủ thuật tiện lợi. Bạn có thể giải thích tại sao conv=notrunccần thiết?
sleske

Có lẽ không phải vậy. gzip -c file | dd of=filexuất hiện để làm việc là tốt.
dùng710307

1
Mọi người trong câu hỏi được liên kết đã thử nó (và tôi cũng đã thử nó); nó không hoạt động nói chung. Có vẻ như nó chỉ hoạt động đối với các tệp rất nhỏ - có thể vì gzip sẽ đọc một tệp nhỏ vào RAM trước khi nén nó. Đối với các tệp lớn (một vài MB), nó không hoạt động, ngay cả khi chúng có thể nén được.
sleske

3
Vâng. Vì vậy, conv = notrunc là cần thiết.
dùng710307

1
Không phải bất cứ lúc nào chương trình nén (ví dụ gzip) ghi nhiều byte dữ liệu và tiêu đề hơn các byte dữ liệu gốc, do đó ghi đè lên một số phần của tệp? Tôi đoán điều này phụ thuộc vào chương trình nén đã chọn. Có ai có ý tưởng làm thế nào để ngăn chặn điều này xảy ra hoặc làm thế nào (im) có thể xảy ra không?
Daniel Böhmer

7

Nó không quá nhiều gzipbzip2ghi đè lên bản gốc. Thay vào đó, họ ghi dữ liệu nén vào đĩa dưới dạng tệp mới và nếu thao tác đó thành công, họ sẽ hủy liên kết tệp không nén ban đầu.

Nếu bạn có đủ RAM, bạn có thể viết một tập lệnh để tạm thời nén các tệp trong tmpfshệ thống tệp, sau đó xóa bản gốc trên đĩa và thay thế bằng phiên bản nén. Có lẽ một cái gì đó như thế này:

# 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

Chỉ cần chú ý đến việc sử dụng bộ nhớ của bạn, vì tmpfsthực chất là một đĩa RAM. Một tệp đầu ra lớn có thể dễ dàng bỏ đói hệ thống và gây ra các vấn đề khác cho bạn.


1
Điều đó đủ điên rồ để làm việc
Andrew Lambert

Tôi thích đẩy phong bì.
James Sneeringer

3

Không có công cụ nào hoạt động theo cách này, chính xác là lý do bạn đưa ra. Rất ít người sẵn sàng viết một công cụ cố tình thực hiện hành vi rủi ro.


Tôi đã hy vọng rằng nó sẽ là một tùy chọn không an toàn, không mặc định cho một tiện ích. Bạn có thể nghĩ về một sự thay thế? Có cách nào để cắt bớt một tập tin tại chỗ không, ví dụ như xóa 2 GB đầu tiên? Điều đó sẽ cho phép tôi sử dụng không gian trống hạn chế của mình để nén từng đoạn một, thu nhỏ tệp nguồn khi tôi đi.
Lee

Thực sự không có cách nào lành mạnh để xóa dữ liệu từ đầu tệp trên bất kỳ hệ thống tệp nào, bằng bất kỳ công cụ nào.
Ignacio Vazquez-Abrams

2
Nhưng bạn có thể xóa dữ liệu từ cuối tập tin. Nó có thể được thực hiện trên nguyên tắc. Bạn cắt dữ liệu ở phần cuối của tệp để đặt vào các tệp riêng biệt, cắt bớt các tệp gốc khi bạn đi. Sau đó, bạn nén các tệp theo thứ tự chuyển tiếp, xóa chúng khi bạn đi. Nó sẽ là một nỗi đau để thực hiện và nếu bất cứ điều gì sai, bạn sẽ bị sai lầm. Nhưng nó có thể.
David Schwartz

1

Các lệnh split và csplit có thể được sử dụng để chia tệp lớn thành các phần nhỏ hơn, sau đó nén chúng riêng lẻ. Việc tập hợp lại sẽ khá tốn thời gian.


Một lựa chọn tốt khác. Một người có thể có thể viết một số kịch bản để làm điều này. Tuy nhiên, điều này mang lại nhiều tệp nén riêng biệt, sẽ cần phải được nối lại sau khi giải nén, điều này không tốt lắm.
sleske
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.