我有一個使用 Ubuntu 的家庭文件伺服器。
最近,我的一個驅動器已滿,所以我又買了一個並把它扔在那裡。
我有一個非常大的資料夾,目錄大小約為1.7T,包含相當數量的檔案。
我用了GCP將檔案從舊驅動器複製到新驅動器,似乎工作正常。
我現在想根據舊磁碟機上的原始目錄驗證新磁碟機上的新目錄,然後再從舊磁碟機中刪除資料以釋放空間。我知道我可以透過 CRC 檢查來做到這一點。
具體來說,我可以如何做到這一點?
答案1
我只需使用diff
命令:
diff -rq --no-dereference /path/to/old/drive/ /path/to/new/drive/
這會讀取並比較目錄樹中的每個檔案並報告任何差異。該-r
標誌以遞歸方式比較目錄,而該-q
標誌只是在文件不同時將訊息打印到屏幕上,而不是打印實際差異(就像對文本文件那樣)。--no-dereference
如果存在不同的符號鏈接,例如在一個目錄中存在符號鏈接,而在其對應的目錄中存在鏈接到的文件的副本,則該標誌可能很有用。
如果diff
命令列印無輸出,這意味著目錄樹確實是相同的;可以運行echo $?
驗證其退出狀態為0
,說明兩組文件是相同的。
我不認為計算 CRC 或校驗和在這種情況下特別有用。如果兩組文件位於不同的系統上,並且每個系統都可以計算自己的文件組的校驗和,因此只需要透過網路發送校驗和,則更有意義。計算校驗和的另一個常見原因是保留校驗和的副本以供將來使用。
答案2
同步通常用於複製文件而不是gcp
,但它也可用於驗證副本,無論副本是如何製作的。簡單地做
rsync -niaHc /origfolder/ /copyfolder
請小心以/
.選項有
-n
請勿複製(不做任何更改)-i
逐項列出差異-a
保留(即比較,因為我們有-n
)權限、所有權、符號連結等並遞歸目錄-H
保留硬連結-c
比較校驗和
輸出顯示一個程式碼,詳細說明每個不同檔案或目錄的差異。如果它們相同則沒有輸出。該程式碼具有一些列YXcstpoguax
,其中每個字元是一個點(.
如果比較的方面沒問題),或者是一個字母:
Y is type of update:
< sent (not appropriate in this case)
> need to copy
c missing file or directory
h is hard link
. no update
* and rest of line is a message, eg *deleting
X file type: f file d dir L symlink D device S special file
c checksum differs. + new item " " same
s size differs
t timestamp differs
p permissions differ
o owner differ
g group differ
u (not used)
a acl differ
x extended attributes differ
例如,
.d..t...... a/b/ directory timestamp differs
cL+++++++++ a/b/d -> /nosuch2 symbolic link missing
cS+++++++++ a/b/f special file missing (a/b/f is a fifo)
>f..t...... a/b/ff file timestamp differs
hf a/b/xx1 => a/b/xx files should be a hard linked
cLc.t...... a/b/z -> /tmp/hi2 symbolic link to different name
cd+++++++++ a/c/ directory missing
>f+++++++++ a/c/i.10 missing file needs to be copied
請參閱man rsync
下文--itemize-changes
以了解更多詳細資訊。如果第三列c
或第四列有差異s
,則表示資料已嚴重損壞。其他標誌(例如不同的權限、所有者或時間戳記)對您來說可能不太重要。如果所有檔案都被標記為“遺失”,那麼您可能沒有提供正確的目錄進行比較。如果您確定,執行不含該-n
標誌的 rsync 將「修復」差異。
答案3
我有同樣的問題,我用過安東尼的回答,有一點扭曲。
如果發生某些硬體故障(例如輸入/輸出錯誤),導致 diff 退出,直接應用他的答案將會失敗。
我整理了他的答案,以及這個答案,並將其全部放入:
find /path/to/original -type f -exec bash -c 'diff -rq --no-dereference "$@" "/path/to/destination/$(sed -r "s/^.*(<first-common-ancestor>.*)$/\1/g" <<<"$@")"' bash {} \;
- 替換
/path/to/original
為您複製的原始目錄的路徑。 - 替換
/path/to/destination
為您複製到的目標目錄的路徑。 - 替換
<first-common-ancestor>
為兩者之間的共同祖先目錄。範例:您正在從 複製/media/foo/bar
到/media/test/dst/
,因此dst
,在複製操作完成後, 具有目錄bar
。第一個共同祖先就bar
在這裡;因為下面的所有文件bar
都將具有相同的相對路徑。
一些注意事項:
bash -c
和部分bash {}
用於對檔案名稱進行安全替換;為了安全起見,不要受到可能的攻擊(例如特權提升)的傷害。- 該
sed
部分是刪除找到的檔案的絕對路徑並僅使用相對路徑(這與 using 不同execdir
)。如果您不確定這有什麼用,請嘗試將其刪除並檢查錯誤訊息:) - 將
<<<
變數作為字串讀取,而不是將其作為要讀取的檔案的路徑讀取。