추가 디스크 공간을 사용하지 않고 Linux에서 파일을 압축하는 방법은 무엇입니까?


20

95GB 파일이있는 100GB 드라이브가 있습니다. 드라이브의 여유 공간을 확보해야합니다 (지금 드라이브에서 파일을 전송하는 것은 옵션이 아닙니다). 이 파일은 잘 압축 것 gzip또는 bz2이든,하지만이 모든 프로그램은 별도의 파일로 압축 된 파일을 작성합니다. 충분한 여유 공간이 없습니다.

표준 압축 도구 또는 다른 Unix 유틸리티를 사용하여 추가 디스크 공간 (또는 최소한의 추가 디스크 공간)을 사용하지 않고 파일을 압축하는 방법이 있습니까? 한 번에 파일의 일부를 압축하고 결과를 파일 위에 직접 쓰는 것을 상상하고 있습니다. 압축이 중단되면 파일이 손상 될 수 있기 때문에 이것이 위험하다는 것을 알고 있지만 선택의 여지가 없다고 생각합니다.


우리가 예전의 장소에서 사용했던 마지막 옵션은 쓰레기로 가득 찬 1G 파일 전체를 포함하는 어딘가에 디렉토리를 두는 것입니다. 그런 다음 꼬집어 들어가면 약간의 비상 공간을 제공하기 위해 일부를 제거 할 수 있습니다.

답변:


13

이것은 개념 증명 bash one-liner이지만, 시작해야합니다. 자신의 책임하에 사용하십시오.

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.3kB) 복사, 2.5855e-05s, 167MB / s

첫 번째 필드는 기록 된 바이트의 정수입니다. 파일을자를 필요가있는 크기입니다. 출력 형식이 항상 동일하다는 것을 100 % 확신하지 못합니다.


멋진 트릭. 왜 conv=notrunc필요한지 설명해 주 시겠습니까?
sleske

아닐 수도 있습니다. gzip -c file | dd of=file잘 작동하는 것 같습니다.
user710307

1
관련 질문에있는 사람들이 시도해 보았습니다 (나도 시도했습니다). 일반적으로 작동하지 않습니다. 아주 작은 파일에서만 작동하는 것 같습니다. 압축하기 전에 gzip이 작은 파일을 RAM으로 읽어 들일 수 있습니다. 큰 파일 (몇 MB)의 경우 압축 가능하더라도 작동하지 않습니다.
sleske

3
네. 따라서 conv = notrunc가 필요합니다.
user710307

1
압축 프로그램 (예 gzip:)이 원래 데이터 바이트보다 더 많은 헤더 및 데이터 바이트를 작성하여 파일의 일부를 덮어 쓰는 것이 가능하지 않습니까? 선택한 압축 프로그램에 따라 달라집니다. 이 문제가 발생하는 것을 방지하는 방법 또는 그것이 어떻게 가능한지 아는 사람이 있습니까?
Daniel Böhmer

7

그것은 너무 많은 아니라 그 gzipbzip2원본을 덮어 씁니다. 대신 압축 된 데이터를 디스크에 새 파일로 기록하고 해당 작업이 성공하면 원래의 압축되지 않은 파일을 연결 해제합니다.

충분한 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

당신이 제공하는 정확한 이유 때문에 이런 식으로 작동하는 도구는 없습니다. 위험한 행동을 의도적으로 구현하는 도구를 기꺼이 작성하는 사람은 거의 없습니다.


유틸리티에 안전하지 않은 기본 옵션이 아니길 바랐습니다. 대안을 생각할 수 있습니까? 예를 들어 처음 2GB를 제거하기 위해 파일을 제자리에 잘리는 방법이 있습니까? 그러면 제한된 여유 공간을 사용하여 한 번에 한 청크를 압축하고 소스 파일을 축소 할 수 있습니다.
Lee

도구를 사용하여 파일 시스템의 파일 시작 부분에서 데이터를 제거 할 수있는 방법은 없습니다.
Ignacio Vazquez-Abrams

2
그러나 파일 에서 데이터를 제거 할 수 있습니다 . 원칙적으로 수행 할 수 있습니다. 파일 끝에서 데이터를 분리하여 별도의 파일을 넣고 원본 파일을 잘라냅니다. 그런 다음 파일을 정방향으로 압축하여 이동하면서 삭제합니다. 구현하기가 어려울 것이며 문제가 발생하면 망할 것입니다. 그러나 가능합니다.
David Schwartz

1

split 및 csplit 명령을 사용하여 큰 파일을 더 작은 부분으로 분할 한 다음 개별적으로 압축 할 수 있습니다. 재 조립은 다소 시간이 걸릴 것입니다.


또 다른 좋은 옵션입니다. 아마도 이것을하기 위해 스크립트를 작성할 수 있습니다. 그러나 이렇게하면 개별적으로 압축 된 많은 파일이 생성되므로 압축 해제 후 다시 연결해야하므로 좋지 않습니다.
sleske
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.