Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to copy and paste a whole directory to a new path recursively?

I want to move a directory as a copy/paste routine, by keeping its structure as it is. I am not looking only for the files within all subfolders in a directory then copy/paste them (as this solution), instead I want to clone the whole thing and keep its structure as it is (Tree -> subfolders and files), exactly like a copy and paste routine.

So I found this function that copies a folder full of files to a new path:

Folder -> File(s)

The function behaves as known as the copy/paste routine. It takes SourcePath, DestinationPath and boolean value to OverWriteExisting. Nice and small but too bad it wasn't marked as the actual answer of that question there (recommend a rate).

But what if I want to move a whole directory? In other words, what if I have a folder that has folders of folders of folders of files and etc? And maybe it is unknown the file structure tree size like this:

Folder -> Folder(s) -> ... -> Folder(s) -> File(s)

I am using the below routine to copy/paste a folder that has folders. But here I know that I only have one level of folders so only one foreach loop is required:

foreach (var Folder in DestinationFolder) // here I know that I have only one level of folders to reach the files
{
    CopyDirectory(FolderPath, DestinationPath, false); // use that function to copy the files
}

This above function serves this directory structure:

Folder -> Folder(s) -> File(s)

I tried this and it didn't do what I want. I only retrieve all files while it searches all the subfolders. Which is not what I want. I want to keep the subfolders and the original structure as it is. Here I get four files instead of the directory structed as it is, subfolders and their subfolders, subfolders, files. Only four because it removes duplicates which I do not want this to happen because I need all of them.

Here is my current structure(but my question is global to any directory):

Folder -> Folders -> Folders + Files

Here is what the below code does in the new path:

NewFolder -> AllFilesFoundInAnySubfolder

dialog.FileName = dialog.FileName.Replace(".xml", ""); // get the destination path
DirectoryInfo dirInfo = new DirectoryInfo(dialog.FileName);

if (dirInfo.Exists == false)
    Directory.CreateDirectory(dialog.FileName);

List<String> EverythingInTheDirectory = Directory
                    .GetFiles(FileStructure.baseSessionPath + "\\" + SelectedSession.Name, "*.*", SearchOption.AllDirectories).ToList(); // source

foreach (string file in EverythingInTheDirectory)
{
    FileInfo mFile = new FileInfo(file);
    // to remove name collusion
    if (new FileInfo(dirInfo + "\\" + mFile.Name).Exists == false)
        mFile.MoveTo(dirInfo + "\\" + mFile.Name);
}

How to move the whole directory with unknown size and keep its structure as it is? Not get only the files from a directory and move them!

like image 460
Khalil Khalaf Avatar asked Oct 17 '25 14:10

Khalil Khalaf


2 Answers

Here is an example that will recursively clone a directory to another destination directory.

class Program
{
    static void Main(string[] args)
    {
        CloneDirectory(@"C:\SomeRoot", @"C:\SomeOtherRoot");
    }

    private static void CloneDirectory(string root, string dest)
    {
        foreach (var directory in Directory.GetDirectories(root))
        {
            //Get the path of the new directory
            var newDirectory = Path.Combine(dest, Path.GetFileName(directory));
            //Create the directory if it doesn't already exist
            Directory.CreateDirectory(newDirectory);
            //Recursively clone the directory
            CloneDirectory(directory, newDirectory);
        }

        foreach (var file in Directory.GetFiles(root))
        {
            File.Copy(file, Path.Combine(dest, Path.GetFileName(file)));
        }
    }
}
like image 200
hawkstrider Avatar answered Oct 21 '25 13:10

hawkstrider


A slight variation on code by @hawkstrider .

private static void CloneDirectory(DirectoryInfo source, DirectoryInfo dest) {
    foreach (var source_subdir in source.EnumerateDirectories()) {
        var target_subdir = new DirectoryInfo(Path.Combine(dest.FullName, source_subdir.Name));
        target_subdir.Create();
        CloneDirectory(source_subdir, target_subdir);
    }

    foreach (var source_file in source.EnumerateFiles()) {
        var target_file = new FileInfo(Path.Combine(dest.FullName, source_file.Name));
        source_file.CopyTo(target_file.FullName, true);
    }
}

EDIT:
As @EtiennedeMartel correctly states, the Create() doesn't need the Exists check. ms-docs
Also Enumerations FTW!

like image 39
Xan-Kun Clark-Davis Avatar answered Oct 21 '25 11:10

Xan-Kun Clark-Davis