簡體   English   中英

從目錄遞歸最小復制文件

[英]Copy files from directory recursively smallest first

我想所有目錄中的文件復制到使用Visual C#.NET版本3.5中的目標文件夾,它可以很容易地完成(取自答案):

private static void Copy(string sourceDir, string targetDir)
{
    Directory.CreateDirectory(targetDir);

    foreach (var file in Directory.GetFiles(sourceDir))
        File.Copy(file, Path.Combine(targetDir, Path.GetFileName(file)));

    foreach (var directory in Directory.GetDirectories(sourceDir))
        Copy(directory, Path.Combine(targetDir, Path.GetFileName(directory)));
}

現在,這里有一個小問題:我希望它首先對所有文件進行最小排序,因此,如果源路徑是可移動驅動器,一段時間后將其拔出,則仍將復制大多數數據。 使用高級算法時,如果先獲取包含大文件的目錄,然后再包含包含許多小文件的目錄,則用戶有可能在軟件仍在復制大文件時將驅動器拔出,而不會留下任何東西在驅動器上,但不完整的大文件除外。

我的想法是做多個循環:首先,將每個文件路徑放入包含其大小的字典中,然后對該字典進行排序,然后將每個文件從源復制到目標(包括創建文件夾)。

恐怕這不是一個很整潔的解決方案,因為對我來說,兩次循環差不多是不合適的。 另外,如果源文件夾中包含太多不同的文件和子文件夾,我不確定我的詞典是否可以存儲那么多信息。

有什么更好的選擇嗎?

您可以基於以下事實使用更簡單的方法:您可以在目錄子樹中獲取所有文件,而無需使用遞歸即可。

問題的缺失部分是文件大小。 可以使用DirectoryInfo類和FileInfo類獲得此信息,而排序只是應用於文件序列的Linq指令,如以下示例所示。

private static void Copy(string sourceDir, string targetDir)
{
    DirectoryInfo di = new DirectoryInfo(sourceDir);
    foreach (FileInfo fi in di.GetFiles("*.*", SearchOption.AllDirectories).OrderBy(d => d.Length))
    {
        string leftOver = fi.DirectoryName.Replace(sourceDir, "");
        string destFolder = Path.Combine(targetDir, leftOver);

        // Because the files are listed in order by size
        // we could copy a file deep down in the subtree before the 
        // ones at the top of the sourceDir

        // Luckily CreateDirectory doesn't throw if the directory exists
        // and automatically creates all the intermediate folders required
        Directory.CreateDirectory(destFolder);

        // Just write the intended copy parameters as a proof of concept
        Console.WriteLine($"{fi.Name} with size = {fi.Length} -> Copy from {fi.DirectoryName} to {Path.Combine(destFolder, fi.Name)}");
    }
}

在此示例中,我已使用Console.WriteLine更改了File.Copy方法,只是為了獲得概念證明而無需復制任何內容,但是替換很簡單。

還要注意,最好使用EnumerateFiles代替GetFilesMSDN文檔中所述

我希望這有幫助!

第一; 從源目錄獲取所有文件,遞歸是可選的。 然后繼續將按大小排序的所有文件復制到目標目錄。

void CopyFiles(string sourceDir, string targetDir, bool recursive = false)
{
    foreach (var file in GetFiles(sourceDir, recursive).OrderBy(f => f.Length))
    {
        var subDir = file.DirectoryName
            .Replace(sourceDir, String.Empty)
            .TrimStart(Path.DirectorySeparatorChar);
        var fullTargetDir = Path.Combine(targetDir, subDir);

        if (!Directory.Exists(fullTargetDir))
            Directory.CreateDirectory(fullTargetDir);

        file.CopyTo(Path.Combine(fullTargetDir, file.Name));
    }
}

IEnumerable<FileInfo> GetFiles(string directory, bool recursive)
{
    var files = new List<FileInfo>();

    if (recursive)
    {
        foreach (var subDirectory in Directory.GetDirectories(directory))
            files.AddRange(GetFiles(subDirectory, true));
    }

    foreach (var file in Directory.GetFiles(directory))
        files.Add(new FileInfo(file));

    return files;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM