Shell

刪除gz文件的最後一行

  • September 25, 2017

我需要在不解壓縮的情況下刪除 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 文件:

  1. 在記憶體中解壓縮它以確定要截斷它的位置;
  2. 截斷文件以刪除要保留的最後一個字元之後的所有數據;
  3. 覆蓋最後幾個字節以正確編碼最後一個字元;
  4. 在開頭覆蓋幾個字節以反映新文件的大小。

然而,這不能用標準工具來完成,它需要一些自定義程式,並且如果它被中斷會留下一個無效的文件。

引用自:https://unix.stackexchange.com/questions/294710