仅在C#中复制新的或修改的文件/目录

时间:2019-03-21 15:01:32

标签: c# copy filesystems

我试图在C#中创建一个简单的“目录/文件复制”控制台应用程序,我需要将所有文件夹和文件(保持原始层次结构)从一个驱动器复制到另一个驱动器,例如从驱动器C:\ Data驱动E:\ Data。

但是,我只希望它将任何新文件或修改过的文件从源复制到目标。 如果目标驱动器上的文件比源驱动器上的文件新,则不会复制。

(问题)

在我拥有的代码中,它将源中的文件“ abc.pdf”与目标中的文件“ xyz.pdf”进行比较,因此即使目标文件是较新的,也将用源文件中的内容覆盖目标文件。我试图弄清楚如何比较源中的“ abc.pdf”和目标中的“ abc.pdf”。

如果我将源和目标向下钻取到特定文件,则此方法有效,但是当我退回到文件夹级别时,即使目标文件是较新的,它也会用源文件覆盖目标文件。

(我的解决方案–没用)

我认为通过在“ foreach”命令之后放置“ if(file.LastWriteTime> destination.LastWriteTime)”,可以比较两个文件夹中的文件,即File1源文件和File1目标文件,但不是。

似乎我在“ FileInfo []”,“ foreach”或“ if”语句中缺少某些内容,无法进行一对一的比较。我认为可能是对“ Path.Combine”语句或“ SearchOption.AllDirectories”的引用,但我不确定。

有什么建议吗?

从我的基本代码示例中可以看到,我是C#的新手,所以请用简单的术语来回答。

谢谢。

这是我尝试过的代码,但是没有用。


class Copy  
{  
    public static void CopyDirectory(DirectoryInfo source, DirectoryInfo destination)  
    {  
        if (!destination.Exists)  
        {  
            destination.Create();  
        }  
        // Copy files.  
        FileInfo[] files = source.GetFiles();  
        FileInfo[] destFiles = destination.GetFiles();  
        foreach (FileInfo file in files)  
            foreach (FileInfo fileD in destFiles)  
                // Copy only modified files    
                    if (file.LastWriteTime > fileD.LastWriteTime)  
                    {  
                        file.CopyTo(Path.Combine(destination.FullName,  
                        file.Name), true);  
                    }  

                // Copy all new files  
                else  
                if (!fileD.Exists)  
                {  
                    file.CopyTo(Path.Combine(destination.FullName, file.Name), true);  
                }  
        // Process subdirectories.  
        DirectoryInfo[] dirs = source.GetDirectories();  
        foreach (DirectoryInfo dir in dirs)  
        {  
            // Get destination directory.  
            string destinationDir = Path.Combine(destination.FullName, dir.Name);  
            // Call CopyDirectory() recursively.  
            CopyDirectory(dir, new DirectoryInfo(destinationDir));  
        }  
    }  
}  

2 个答案:

答案 0 :(得分:0)

您只需在“源”中获取文件数组,然后在“目标”中检查匹配的名称

/// <summary>
    /// checks whether the target file needs an update (if it doesn't exist: it needs one)
    /// </summary>
    public static bool NeedsUpdate(FileInfo localFile, DirectoryInfo localDir, DirectoryInfo backUpDir)
    {
        bool needsUpdate = false;

        if (!File.Exists(Path.Combine(backUpDir.FullName, localFile.Name)))
        {
            needsUpdate = true;
        }
        else
        {
            FileInfo backUpFile = new FileInfo(Path.Combine(backUpDir.FullName, localFile.Name));

            DateTime lastBackUp = backUpFile.LastWriteTimeUtc;
            DateTime lastChange = localFile.LastWriteTimeUtc;

            if (lastChange != lastBackUp)
            {
                needsUpdate = true;
            }
            else
            {/*no change*/}
        }
        return needsUpdate;
    }

答案 1 :(得分:0)

更新:

我按照上面的建议修改了代码,一切顺利。它完全符合我的预期。

但是,我遇到的问题是在大型文件夹上运行应用程序所花费的时间。 (包含6,000个文件和5个子文件夹)

在一个小文件夹(5个子文件夹中的28个文件)上,只需花费几秒钟即可运行。但是,在较大的文件夹上,只花了35分钟即可处理1300个文件。

解决方案:

下面的代码将执行相同的操作,但速度要快得多。这个新版本在大约10秒钟内处理了6,000个文件。它在大约1分钟50秒内处理了40,000个文件。

此新代码可以(不可以)做什么

如果目标文件夹为空,请将所有文件从源复制到目标。

如果目标与源具有部分或全部相同的文件/文件夹,请比较并将任何新文件或修改过的文件从源复制到目标。

如果目标文件比源文件新,请不要复制。

因此,这是实现它的代码。享受和分享。

感谢所有帮助我对此有所了解的人。



    using System;
    using System.IO;


    namespace VSU1vFileCopy
    {
        class Program
        {
            static void Main(string[] args)
            {
                const string Src_FOLDER = @"C:\Data";
                const string Dest_FOLDER = @"E:\Data";
                string[] originalFiles = Directory.GetFiles(Src_FOLDER, "*", SearchOption.AllDirectories);

                Array.ForEach(originalFiles, (originalFileLocation) =>
                {
                    FileInfo originalFile = new FileInfo(originalFileLocation);
                    FileInfo destFile = new FileInfo(originalFileLocation.Replace(Src_FOLDER, Dest_FOLDER));

                    if (destFile.Exists)
                    {
                        if (originalFile.Length > destFile.Length)
                        {
                            originalFile.CopyTo(destFile.FullName, true);
                        }
                    }
                    else
                    {
                        Directory.CreateDirectory(destFile.DirectoryName);
                        originalFile.CopyTo(destFile.FullName, false);
                    }
                });
            }
        }
    }