Shell
刪除gz文件的最後一行
我需要在不解壓縮的情況下刪除 gz 文件的最後一行。該文件有 500 行。
我怎樣才能做到這一點?
我試過了:
gzip -dc "$files" | tail -500 | gzip -c > "$files".tmp
但它不起作用。
您無法在不解壓縮的情況下修改壓縮文件。
至少,要刪除第 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 文件:
- 在記憶體中解壓縮它以確定要截斷它的位置;
- 截斷文件以刪除要保留的最後一個字元之後的所有數據;
- 覆蓋最後幾個字節以正確編碼最後一個字元;
- 在開頭覆蓋幾個字節以反映新文件的大小。
然而,這不能用標準工具來完成,它需要一些自定義程式,並且如果它被中斷會留下一個無效的文件。