Bash

用於重寫目錄樹中所有文件的命令行工具

  • March 28, 2021

是否有命令行工具可用於就地或通過創建新的 inode 重寫目錄樹中的所有正常文件?

就地重寫文件,我的意思是打開文件進行讀寫,讀取合理大小的塊並將這些塊寫入同一位置,對整個文件執行此操作。基本上這個命令行的作用是:

find dir -type f -print0 | xargs -0 -n1 bash -c 'dd if="$1" of="$1" conv=notrunc bs=64M' -

如果創建了一個新的 inode,文件屬性應該盡可能好地被替換,例如這個命令的作用:

find dir -type f -print0 | xargs -0 -n1 bash -c 'echo "$1"; cp -a "$1" "$1~" && mv "$1~" "$1"' -

背景:

我正在嘗試獲得一些經驗,並在適當的情況下尋找使用 ZFS 重複數據刪除的良好做法。ZFS 重複數據刪除使用DDT(重複數據刪除表)並對大小由文件的記錄大小指定的塊進行操作*,*這會影響重複數據刪除的有效性和記憶體使用情況。我正在探索遷移已經寫入的數據以使用或停止使用 DDT 或更改文件的記錄大小的可能性。ZFS 不會自動更改已寫入數據的這些參數,因此需要重寫數據。

要更改是否使用 DDT,只需在原地重寫數據(無需創建新文件)即可。但是文件的記錄大小是在創建時確定的,因此需要創建一個新文件來更改它。

我剛剛創建了可以做到這一點的工具:

https://github.com/pjd/filerewrite

或者,對於 ZFS,您還可以在目標文件系統已打開重複數據刪除的情況下使用 zfs send/recv。之後,您將需要重命名文件系統並確保所有其他文件系統屬性都已移動。

(這個問題在我寫這篇文章時已經有一年了,但它出現在我的審查隊列中,所以我會回答它,以防其他人搜尋類似的需求。)

這種工具不太可能存在並且在不同的文件系統類型中是可靠的,尤其是在可能在系統根樹的不同點安裝多種文件系統類型的 *nix 系統中。這樣做的原因是某些文件系統可能會“在後台”做額外的工作,並且不能保證重寫會發生在同一個地方,(實際上,你想要做的 - 讓 ZFS 完全做到這一點通過重寫文件數據來進行重複數據刪除!)除非文件系統本身已經支持這樣的功能。

您可以編寫一個快速程序以讀寫模式打開文件,然後讀取一個塊,返回塊的開頭,然後再次寫入。我不知道這是否適用於 ZFS 重複數據刪除,或者您可能會遇到哪些其他類型的問題。例如,加密文件系統可能需要重新加密文件,和/或什至移動文件在物理儲存設備上的物理儲存位置。這就是您需要自己編寫這樣一個工具以滿足您的特定需求的部分原因。

另一種方法是備份文件樹,然後在原始文件上恢復備份。然而,如前所述,這需要您有某種備份儲存(儘管它可以是同一物理磁碟上其他地方的簡單 tar 文件等),並適當地選擇備份和恢復選項。

作為最後的手段,您可以在別處重命名目錄樹,然後通過一次複製一個文件來重新創建它(在確認新文件已安全複製後刪除舊文件,以釋放空間)。您仍然需要足夠的額外儲存空間來複製最大的單個文件。這在大多數情況下是不容易避免的,特別是如果文件系統驅動程序試圖足夠高效地意識到數據實際上沒有改變(例如,保持塊雜湊/校驗和)並簡單地丟棄不必要的寫入。對於電腦而言,記憶體到/從記憶體的操作比記憶體到/從設備的操作要快得多。

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