簡體   English   中英

Directory.Move 不起作用(文件已存在)

[英]Directory.Move doesn't work (file already exist)

我有主文件夾:

c:\test

在那里我有 2 個文件夾:電影和照片。

照片有三個文件夾,其中的文件具有相同的結構:人物、動物和建築物。 我正在嘗試這個代碼:

Directory.Move(@"c:\test\Movies", @"c:\test\Test");

我得到例外:

File already exists

此方法將遞歸移動文件夾的內容並覆蓋現有文件。
您應該添加一些異常處理。
編輯:
這個方法是用一個while循環和一個堆棧而不是遞歸來實現的。

public static void MoveDirectory(string source, string target)
{
    var stack = new Stack<Folders>();
    stack.Push(new Folders(source, target));

    while (stack.Count > 0)
    {
        var folders = stack.Pop();
        Directory.CreateDirectory(folders.Target);
        foreach (var file in Directory.GetFiles(folders.Source, "*.*"))
        {
             string targetFile = Path.Combine(folders.Target, Path.GetFileName(file));
             if (File.Exists(targetFile)) File.Delete(targetFile);
             File.Move(file, targetFile);
        }

        foreach (var folder in Directory.GetDirectories(folders.Source))
        {
            stack.Push(new Folders(folder, Path.Combine(folders.Target, Path.GetFileName(folder))));
        }
    }
    Directory.Delete(source, true);
}
public class Folders
{
    public string Source { get; private set; }
    public string Target { get; private set; }

    public Folders(string source, string target)
    {
        Source = source;
        Target = target;
    }
}

更新:
這是一個更簡單的版本,遞歸使用Directory.EnumerateFiles而不是使用堆棧。
這僅適用於 .net 4 或更高版本,對我們而言,使用早期版本的 .net 將Directory.EnumerateFiles更改為Directory.GetFiles

public static void MoveDirectory(string source, string target)
{
    var sourcePath = source.TrimEnd('\\', ' ');
    var targetPath = target.TrimEnd('\\', ' ');
    var files = Directory.EnumerateFiles(sourcePath, "*", SearchOption.AllDirectories)
                         .GroupBy(s=> Path.GetDirectoryName(s));
    foreach (var folder in files)
    {
        var targetFolder = folder.Key.Replace(sourcePath, targetPath);
        Directory.CreateDirectory(targetFolder);
        foreach (var file in folder)
        {
            var targetFile = Path.Combine(targetFolder, Path.GetFileName(file));
            if (File.Exists(targetFile)) File.Delete(targetFile);
            File.Move(file, targetFile);
        }
    }
    Directory.Delete(source, true);
}

目標目錄不應存在 - Directory.Move 方法為您創建目標目錄。

ProcessStartInfo p = new ProcessStartInfo("cmd", "/c move \"c:\\test\\Movies\" \"c:\\test\Test\\"");
p.WindowStyle = ProcessWindowStyle.Hidden; //hide mode
Process.Start(p);

Directory.Move可能失敗的最常見的 2 個原因是:

  • 這是一個不同的卷(你需要復制/刪除)
  • 已經存在(默認不支持覆蓋)

這是我對第二個問題的簡單解決方案(覆蓋):

public bool MoveDirectory(string sourceDirName, string destDirName, bool overwrite)
{
    if (overwrite && Directory.Exists(destDirName))
    {
        var needRestore = false;
        var tmpDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
        try
        {
            Directory.Move(destDirName, tmpDir);
            needRestore = true; // only if fails
            Directory.Move(sourceDirName, destDirName);
            return true;
        }
        catch (Exception)
        {
            if (needRestore)
            {
                Directory.Move(tmpDir, destDirName);
            }
        }
        finally
        {
            Directory.Delete(tmpDir, true);
        }
    }
    else
    {
        Directory.Move(sourceDirName, destDirName); // Can throw an Exception
        return true;
    }
    return false;
}

在將新內容復制到目標文件夾之前刪除目標文件夾是否安全?

    Directory.Delete(@"c:\test\test");
    Directory.Move(@"c:\test\movies",@"c:\test\test");

您可以直接使用移動​​方法。

Directory.Move(@"c:\test\Movies\", @"c:\test\Test\");

該文件夾將被刪除並將其復制到測試文件夾中。

暫無
暫無

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

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