using System.Threading.Tasks;
public static async Task Main()
Directory.CreateDirectory("foo/bar");
Directory.CreateDirectory("foo/empty");
File.Create("foo/foo_file1.txt");
File.Create("foo/bar/bar_file1.txt");
var oldDirectory = Path.GetFullPath(oldPath);
var oldDirectoryParent = Path.GetDirectoryName(oldDirectory);
var newDirectory = Path.Combine(oldDirectoryParent, newPath);
Directory.CreateDirectory(newDirectory);
.EnumerateFileSystemEntries(oldDirectory, "*.*", SearchOption.AllDirectories);
var filesAndFolders = paths.ToLookup(Directory.Exists);
var directoryTasks = filesAndFolders[true]
.Select(path => newDirectory + path.Substring(oldDirectory.Length))
.Select(CreateDirectoryAsync);
await Task.WhenAll(directoryTasks);
var fileTasks = filesAndFolders[false]
.Select(path => newDirectory + path.Substring(oldDirectory.Length))
await Task.WhenAll(fileTasks);
foreach (var entry in Directory.EnumerateFileSystemEntries(newDirectory, "*.*", SearchOption.AllDirectories))
Console.WriteLine(entry);
public static Task<FileStream> CreateAsync(string path) => Task.Run(() => File.Create(path));
public static Task<DirectoryInfo> CreateDirectoryAsync(string path) => Task.Run(() => Directory.CreateDirectory(path));