C# 比較兩個路徑下的檔案,將差異檔案複製到新路徑

目前筆者在上版的時候,需要遠端連線到客戶的跳板機,再遠端連線至目標主機做更新。而檔案也需要先發布、壓縮、複製兩次、解壓縮、取代舊檔案。而因為目標主機效能問題,解壓縮和取代通常都需要花費 10 分鐘以上,為了方便,通常會先找到差異檔案,只取代差異檔案,以節省時間。

只是尋找差異檔案非常麻煩,有時候還要手動建立資料夾,也很浪費時間。於是筆者就寫了下面的小程式,方便比較兩者的檔案,並將需要更新的檔案複製到指定路徑下。

功能: 將 sourceDir 資料夾和 targetDir 資料夾的檔案做比較,將存在於 sourceDir 資料夾內的檔案但不在 targetDir 資料夾內或與 targetDir 內相對路徑的檔案內容不同時,複製到 copyToDir 資料夾內的相對路徑。

已知問題: 若包含在 targetDir 但不包含在 sourceDir 中,不會有任何提示或複製。

完整程式碼:
    
class Program
{
    static void Main(string[] args)
    {
        string sourceDir = @"C:\Users\ruyut\Desktop\source"; // 欲比較的來源路徑
        string targetDir = @"C:\Users\ruyut\Desktop\target"; // 欲比較的目標路徑
        string copyToDir = @"C:\Users\ruyut\Desktop\copyto"; // 要複製到的目標路徑

        CopyDiffFiles(sourceDir, targetDir, copyToDir);
    }

    /// <summary>
    /// 複製不同的檔案
    /// </summary>
    /// <param name="sourceDir">欲比較的來源路徑</param>
    /// <param name="targetDir">欲比較的目標路徑</param>
    /// <param name="copyToDir">要複製到的目標路徑</param>
    private static void CopyDiffFiles(string sourceDir, string targetDir, string copyToDir)
    {
        // 找出來源路徑中的所有檔案
        string[] sourceFiles = Directory.GetFiles(sourceDir, "*", SearchOption.AllDirectories);

        // 對於每個檔案,檢查其是否在目標目錄中存在,並檢查兩個檔案是否相同
        foreach (string file in sourceFiles)
        {
            // 計算目標檔案的完整路徑
            string relativePath = file.Substring(sourceDir.Length + 1);
            string targetFile = Path.Combine(targetDir, relativePath);

            if (!File.Exists(targetFile) || !AreFilesEqual(file, targetFile))
            {
                // 計算要複製到的目標檔案的完整路徑
                string copyToFile = Path.Combine(copyToDir, relativePath);

                // 檢查資料夾
                Directory.CreateDirectory(Path.GetDirectoryName(copyToFile));
                File.Copy(file, copyToFile, true);
                Console.WriteLine("Copied {0} to {1}", file, copyToFile);
            }
        }
    }

    /// <summary>
    /// 確認檔案是否相同
    /// </summary>
    private static bool AreFilesEqual(string file1, string file2)
    {
        byte[] file1Bytes = File.ReadAllBytes(file1);
        byte[] file2Bytes = File.ReadAllBytes(file2);
        if (file1Bytes.Length != file2Bytes.Length) return false;
        for (int i = 0; i < file1Bytes.Length; i++)
        {
            if (file1Bytes[i] != file2Bytes[i]) return false;
        }

        return true;
    }
}
    

留言