압축을 풀지 않고 gz 파일의 마지막 줄을 제거해야 합니다. 파일에는 500줄이 있습니다.
어떻게 해야 하나요?
나는 시도했다:
gzip -dc "$files" | tail -500 | gzip -c > "$files".tmp
하지만 작동하지 않습니다.
답변1
압축을 풀지 않고는 압축 파일을 수정할 수 없습니다.
최소한 499행 이후의 모든 텍스트를 제거하려면 처음 499행의 압축을 풀어 499행이 끝나는 위치를 찾아야 합니다. 줄 수에 관계없이 마지막 줄을 삭제하려면 전체 파일의 압축을 풀어서 마지막 줄이 시작되는 위치를 확인해야 합니다.
파일이 압축되어 있기 때문에 바로가기가 없습니다. 문자 인코딩은 이전의 모든 문자에 따라 달라집니다. gzip 압축의 기본 원칙은 이전에 발견된 문자 시퀀스에 대해 더 짧은 비트 시퀀스를 사용하고 아직 발견되지 않은 문자 시퀀스에 대해 약간 더 긴 비트 시퀀스를 사용하는 것입니다. 문자 시퀀스가 반복되면 더 작은 파일이 생성됩니다. 이전 문자를 모두 확인하지 않고는 특정 문자가 개행 문자인지 확인할 수 있는 방법이 없습니다.
파일의 압축을 풀고 압축이 풀린 스트림을 처리한 다음 다른 파일로 다시 압축하려는 시도가 정확합니다. 파일을 자르려면 올바른 명령이 필요합니다. tail -500
원하는 것이 아닌 마지막 500줄을 유지하세요. head -n 499
처음 499개 행을 유지하거나 head -n -1
마지막 행을 삭제하는 데 사용됩니다 . 모든 시스템이 부정적인 인수를 지원하는 것은 아닙니다 head
. 그렇지 않은 경우 대신 사용할 수 있습니다 sed '$d'
.
gunzip <"$file" | head -n -1 | gzip >"$file".tmp
mv -- "$file".tmp "$file"
파일에 직접 쓸 수는 없습니다. 파일을 읽는 동안 파일 덮어쓰기가 시작됩니다. gunzip <"$file" | … | gzip >"$file"
gunzip
파이프라인의 명령은 병렬로 실행됩니다. 임시 파일을 생성하지 않는 것이 가능하지만 그렇게 하면 명령이 중단되면 파일이 잘릴 수 있으므로 좋은 생각이 아닙니다. 따라서 이 작업을 수행하는 방법에 대해서는 다루지 않겠습니다.
이론적으로 gzip 압축 파일은 다음과 같은 방법으로 잘릴 수 있습니다.
- 잘라낼 위치를 결정하기 위해 메모리에서 압축을 푼다.
- 유지할 마지막 문자 뒤의 모든 데이터를 제거하려면 파일을 자릅니다.
- 마지막 문자를 올바르게 인코딩하려면 마지막 몇 바이트를 덮어씁니다.
- 새 파일 크기를 반영하도록 처음 몇 바이트를 덮어씁니다.
그러나 이는 표준 도구를 사용하여 수행할 수 없으며 일부 사용자 정의 프로그래밍이 필요하며 중단되면 잘못된 파일이 남게 됩니다.
답변2
예제에서 스트림으로 압축을 푸는 것은 괜찮지만 파일로 압축을 풀지 않기를 원한다고 가정합니다. 당신은 할 수 있어야합니다
gzip -cd "$files" | sed -e '$d' | gzip > "$files".tmp
sed
마지막 행으로 이동하여 삭제하세요 .
답변3
당신은 그것을 사용할 수 있습니다 zcat
.
zcat <file> | head -n <lines>
압축을 푸는 것만으로도 라인을 스트리밍하기에 충분합니다 n
.
답변4
@Eric Renouf의 답변(죄송합니다. 댓글이 너무 길어서)을 기반으로 원본 타임스탬프와 파일 이름 메타데이터를 파일에 유지하려면 다음으로 래핑하세요.
gzip -cd "$file" | sed -e '$d' > "$file.tmp"
touch -r "$file" "$file.tmp"
# optionally keep the old file
# mv "$files" "$file.old"
mv "$file.tmp" "$file"
gzip "$file"
또는 압축되지 않은 파일이 있으므로 다시 압축하는 xz
대신 a를 사용하세요 gzip
. 압축률이 향상되고 일반적으로 더 빠릅니다.