CodeGym /Courses /C# SELF /Copying files and directories

Copying files and directories

C# SELF
Level 40 , Lesson 2
Available

1. Copying files

So far our filesystem operations were kind of "single strike": create a file, read it, delete it — done. But in the real world you often need to copy content: backups, duplicating templates, automating data workflows. Copying sounds trivial (Ctrl+C and Ctrl+V for the win), but there are plenty of nuances.

Today we'll go over all ways to copy files and folders — from the simplest to slightly more advanced. We'll also see how built-in .NET classes handle this, what limitations exist, what errors can trip you up and what to do if you suddenly have two thousand directories and a million files.

Class File and method Copy

The simplest way to copy a file is to use the static method File.Copy. This method takes the source file path, the destination file path and an optional parameter: whether to allow overwriting if the file already exists.

using System.IO;

// Simple example of copying a file
File.Copy("source.txt", "destination.txt");

If the destination file already exists, the method will throw an exception. To explicitly allow overwriting, use the third parameter:

File.Copy("source.txt", "destination.txt", overwrite: true);

Important note: If the second parameter ("destination.txt") is the path to an existing directory rather than a file, you'll get an error. The method expects a path to a file!

Working with paths

As before, don't forget to use Path.Combine so you don't fall into traps with doubled or backslashes:

string sourcePath = Path.Combine("Data", "input.txt");
string destPath = Path.Combine("Backup", "input_backup.txt");

File.Copy(sourcePath, destPath, overwrite: true);

Error handling

What can go wrong when copying a file? Lots: the file might be locked by another process, the source file might be missing, you might lack permissions, the destination disk might be full. Use exception handling:

try
{
    File.Copy("bigdata.txt", "bigdata_backup.txt", overwrite: false);
    Console.WriteLine("File copied successfully!");
}
catch (IOException ex)
{
    Console.WriteLine($"I/O error: {ex.Message}");
}
catch (UnauthorizedAccessException)
{
    Console.WriteLine("No access to the file or folder.");
}
catch (Exception ex)
{
    Console.WriteLine($"Other error: {ex.Message}");
}

Class FileInfo and method CopyTo

If you already have a FileInfo object, you can call CopyTo on it:

var fi = new FileInfo("report.xlsx");
fi.CopyTo("backup_report.xlsx");

The third argument (overwrite) in CopyTo appeared only in .NET Core 2.0+, so if you're targeting an older framework version — don't be surprised by an error.

Copying a file "into nowhere" (or "not caught — not stolen")

Pay attention to the destination path when copying. If the destination folder doesn't exist, .NET will throw. So before copying a file it's a good idea to ensure the target directory exists:

string backupDir = "Backup";
if (!Directory.Exists(backupDir))
{
    Directory.CreateDirectory(backupDir);
}

string targetPath = Path.Combine(backupDir, "mydoc.txt");
File.Copy("mydoc.txt", targetPath);

2. Copying directories: not for the faint-hearted

This is where the real adventures begin! .NET doesn't provide a magical Directory.Copy that does it all in one line (like File). You'll have to do some manual work and write a function to recursively copy all files and subfolders.

Why isn't there a Directory.Copy?

Directory copying isn't always trivial. Each folder can contain files, subfolders, hidden files, files with special permissions and long paths. So the .NET folks decided: "Let programmers decide what to copy." But we don't take the easy route — we'll write our own function!

Example of recursive directory copying

Task: copy the contents of one folder (and all its sub-universe) into another.

using System;
using System.IO;

void CopyDirectory(string sourceDir, string destDir, bool recursive)
{
    // Check if the source folder exists
    if (!Directory.Exists(sourceDir))
        throw new DirectoryNotFoundException($"Source folder not found: {sourceDir}");

    // Create destination folder if it doesn't exist yet
    if (!Directory.Exists(destDir))
        Directory.CreateDirectory(destDir);

    // Copy all files
    foreach (string filePath in Directory.GetFiles(sourceDir))
    {
        string fileName = Path.GetFileName(filePath);
        string destFilePath = Path.Combine(destDir, fileName);
        File.Copy(filePath, destFilePath, overwrite: true);
    }

    // If recursive — copy all subfolders
    if (recursive)
    {
        foreach (string dirPath in Directory.GetDirectories(sourceDir))
        {
            string dirName = Path.GetFileName(dirPath);
            string destSubDir = Path.Combine(destDir, dirName);
            // Recursive call!
            CopyDirectory(dirPath, destSubDir, recursive);
        }
    }
}

Usage:

CopyDirectory("C:\\MyData", "D:\\Backup\\MyData", recursive: true);

This function creates the directory structure and copies all files, including the contents of subfolders.

We analyze the code and nuances

We first create the destination directory (if it doesn't exist) — otherwise trying to copy files there will fail. Inside each loop we use Path.GetFileName so we don't lose the file or folder name when building the new path.

By the way, if you copy a directory into itself or into its subfolder you'll get epic recursion… and a StackOverflowException. Don't copy "C:\\Data" into "C:\\Data\\Backup". The computer will be upset!

Copying files only (no subfolders)

Sometimes it's enough to copy only top-level files (without descending into subfolders):

void CopyFilesOnly(string sourceDir, string destDir)
{
    if (!Directory.Exists(destDir))
        Directory.CreateDirectory(destDir);

    foreach (string filePath in Directory.GetFiles(sourceDir))
    {
        string fileName = Path.GetFileName(filePath);
        string destFilePath = Path.Combine(destDir, fileName);
        File.Copy(filePath, destFilePath, overwrite: true);
    }
}

Example — implement backup

Let's add this functionality to our "HomeApp" that we've been building through the course. Let it now be able to make a backup of its data.

using System;
using System.IO;

namespace HomeApp
{
    class Program
    {
        static void CopyDirectory(string sourceDir, string destDir, bool recursive)
        {
            if (!Directory.Exists(sourceDir))
                throw new DirectoryNotFoundException($"Source folder not found: {sourceDir}");

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

            foreach (string filePath in Directory.GetFiles(sourceDir))
            {
                string fileName = Path.GetFileName(filePath);
                string destFilePath = Path.Combine(destDir, fileName);
                File.Copy(filePath, destFilePath, overwrite: true);
            }

            if (recursive)
            {
                foreach (string dirPath in Directory.GetDirectories(sourceDir))
                {
                    string dirName = Path.GetFileName(dirPath);
                    string destSubDir = Path.Combine(destDir, dirName);
                    CopyDirectory(dirPath, destSubDir, recursive);
                }
            }
        }

        static void Main(string[] args)
        {
            Console.WriteLine("Enter the path to the working directory:");
            string source = Console.ReadLine()!;
            Console.WriteLine("Enter the path to the backup folder:");
            string dest = Console.ReadLine()!;

            try
            {
                CopyDirectory(source, dest, recursive: true);
                Console.WriteLine("Backup created successfully!");
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error while copying: " + ex.Message);
            }
        }
    }
}

3. Useful nuances

Comparison: file vs directory — table

File Directory
Built-in method
File.Copy
-
Object-oriented
FileInfo.CopyTo
-
Traversal of nesting Not required Requires recursion
Creating structure Automatic Need to create nesting manually
Risk of recursion No Yes — don't copy "into itself"

Practical use and exercises

Copying files and folders is everywhere: from backups to data migration or updating resources in game launchers. These procedures are usually automated so you don't end up doing manual work and saying "oh, I forgot a file!" on Monday morning.

Directory copying is required in scenarios where you need to preserve not only content but the "skeleton" of the structure, including subfolders, nested files and settings.

Checklist for copying (so you don't mess up)

  • Source exists
  • Destination folder exists (create when needed via Directory.CreateDirectory)
  • Overwrite scenario — do you need overwrite: true?
  • Are you copying the folder "into itself"?
  • Are you exceeding path length limits (especially on Windows)?
  • Do you account for hidden/system files?

4. Special cases and common copying errors

Permissions

Copying can fail if your program doesn't have read permissions for source files or write permissions to the destination directory. In that case you'll get an UnauthorizedAccessException. The fix — run the program as administrator (only if it's really necessary!) or choose normal folders for copying.

Locked files

If a file is open in another program (for example, Excel locks it), File.Copy may throw. Make sure the application locking the file doesn't interfere, or implement retry logic (try-catch with retries).

Overwriting files

Which logic to choose: overwrite destination files or leave them alone? For backups it's usually fine to overwrite (overwrite: true), while for duplicating templates you may not want to (overwrite: false).

Copying hidden and system files

By default the methods we used (Directory.GetFiles) return all files, including hidden and system. If you need to skip them, filter explicitly:

foreach (string filePath in Directory.GetFiles(sourceDir))
{
    var attr = File.GetAttributes(filePath);
    if ((attr & FileAttributes.Hidden) == FileAttributes.Hidden)
        continue; // Skip hidden files

    // Rest of copy code
}

Long path errors

Windows long limited paths to about 260 characters for a long time. In modern versions this can be lifted, but if you're working on old systems long paths may be a problem.

Symbolic links and junctions

In specific scenarios directories may contain symbolic links or junctions. Normal copy methods may copy them as regular folders or ignore them. For most learning tasks this doesn't matter, but if you work with system directories — be careful.

2
Task
C# SELF, level 40, lesson 2
Locked
Recursive Folder Copy
Recursive Folder Copy
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION