[c#] Rename a file in C#

How do I rename a file using C#?

This question is related to c# file rename

The answer is


Use:

using System.IO;

string oldFilePath = @"C:\OldFile.txt"; // Full path of old file
string newFilePath = @"C:\NewFile.txt"; // Full path of new file

if (File.Exists(newFilePath))
{
    File.Delete(newFilePath);
}
File.Move(oldFilePath, newFilePath);

You can copy it as a new file and then delete the old one using the System.IO.File class:

if (File.Exists(oldName))
{
    File.Copy(oldName, newName, true);
    File.Delete(oldName);
}

Just add:

namespace System.IO
{
    public static class FileInfoExtensions
    {
        public static void Rename(this FileInfo fileInfo, string newName)
        {
            fileInfo.MoveTo(Path.Combine(fileInfo.Directory.FullName, newName));
        }
    }
}

And then...

FileInfo file = new FileInfo("c:\test.txt");
file.Rename("test2.txt");

You can use File.Move to do it.


I've encountered a case when I had to rename the file inside the event handler, which was triggering for any file change, including rename, and to skip forever renaming of the file I had to rename it, with:

  1. Making its copy
  2. Removing the original
File.Copy(fileFullPath, destFileName); // Both have the format of "D:\..\..\myFile.ext"
Thread.Sleep(100); // Wait for the OS to unfocus the file
File.Delete(fileFullPath);

Move is doing the same = copy and delete old one.

File.Move(@"C:\ScanPDF\Test.pdf", @"C:\BackupPDF\" + string.Format("backup-{0:yyyy-MM-dd_HH:mm:ss}.pdf", DateTime.Now));

I couldn't find an approach which suits me, so I propose my version. Of course, it needs input and error handling.

public void Rename(string filePath, string newFileName)
{
    var newFilePath = Path.Combine(Path.GetDirectoryName(filePath), newFileName + Path.GetExtension(filePath));
    System.IO.File.Move(filePath, newFilePath);
}

None of the answers mention writing a unit testable solution. You could use System.IO.Abstractions as it provides a testable wrapper around FileSystem operations, using which you can create a mocked file system objects and write unit tests.

using System.IO.Abstractions;

IFileInfo fileInfo = _fileSystem.FileInfo.FromFileName("filePathAndName");
fileInfo.MoveTo(Path.Combine(fileInfo.DirectoryName, newName));

It was tested, and it is working code to rename a file.


When C# doesn't have some feature, I use C++ or C:

public partial class Program
{
    [DllImport("msvcrt", CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
    public static extern int rename(
            [MarshalAs(UnmanagedType.LPStr)]
            string oldpath,
            [MarshalAs(UnmanagedType.LPStr)]
            string newpath);

    static void FileRename()
    {
        while (true)
        {
            Console.Clear();
            Console.Write("Enter a folder name: ");
            string dir = Console.ReadLine().Trim('\\') + "\\";
            if (string.IsNullOrWhiteSpace(dir))
                break;
            if (!Directory.Exists(dir))
            {
                Console.WriteLine("{0} does not exist", dir);
                continue;
            }
            string[] files = Directory.GetFiles(dir, "*.mp3");

            for (int i = 0; i < files.Length; i++)
            {
                string oldName = Path.GetFileName(files[i]);
                int pos = oldName.IndexOfAny(new char[] { '0', '1', '2' });
                if (pos == 0)
                    continue;

                string newName = oldName.Substring(pos);
                int res = rename(files[i], dir + newName);
            }
        }
        Console.WriteLine("\n\t\tPress any key to go to main menu\n");
        Console.ReadKey(true);
    }
}

  1. First solution

    Avoid System.IO.File.Move solutions posted here (marked answer included). It fails over networks. However, copy/delete pattern works locally and over networks. Follow one of the move solutions, but replace it with Copy instead. Then use File.Delete to delete the original file.

    You can create a Rename method to simplify it.

  2. Ease of use

    Use the VB assembly in C#. Add reference to Microsoft.VisualBasic

    Then to rename the file:

    Microsoft.VisualBasic.FileIO.FileSystem.RenameFile(myfile, newName);

    Both are strings. Note that myfile has the full path. newName does not. For example:

    a = "C:\whatever\a.txt";
    b = "b.txt";
    Microsoft.VisualBasic.FileIO.FileSystem.RenameFile(a, b);
    

    The C:\whatever\ folder will now contain b.txt.


Use:

int rename(const char * oldname, const char * newname);

The rename() function is defined in the stdio.h header file. It renames a file or directory from oldname to newname. The rename operation is the same as move, hence you can also use this function to move a file.


System.IO.File.Move(oldNameFullPath, newNameFullPath);

public static class ImageRename
{
    public static void ApplyChanges(string fileUrl,
                                    string temporaryImageName,
                                    string permanentImageName)
    {
        var currentFileName = Path.Combine(fileUrl,
                                           temporaryImageName);

        if (!File.Exists(currentFileName))
            throw new FileNotFoundException();

        var extention = Path.GetExtension(temporaryImageName);
        var newFileName = Path.Combine(fileUrl,
                                       $"{permanentImageName}
                                         {extention}");

        if (File.Exists(newFileName))
            File.Delete(newFileName);

        File.Move(currentFileName, newFileName);
    }
}

Use:

public static class FileInfoExtensions
{
    /// <summary>
    /// Behavior when a new filename exists.
    /// </summary>
    public enum FileExistBehavior
    {
        /// <summary>
        /// None: throw IOException "The destination file already exists."
        /// </summary>
        None = 0,
        /// <summary>
        /// Replace: replace the file in the destination.
        /// </summary>
        Replace = 1,
        /// <summary>
        /// Skip: skip this file.
        /// </summary>
        Skip = 2,
        /// <summary>
        /// Rename: rename the file (like a window behavior)
        /// </summary>
        Rename = 3
    }


    /// <summary>
    /// Rename the file.
    /// </summary>
    /// <param name="fileInfo">the target file.</param>
    /// <param name="newFileName">new filename with extension.</param>
    /// <param name="fileExistBehavior">behavior when new filename is exist.</param>
    public static void Rename(this System.IO.FileInfo fileInfo, string newFileName, FileExistBehavior fileExistBehavior = FileExistBehavior.None)
    {
        string newFileNameWithoutExtension = System.IO.Path.GetFileNameWithoutExtension(newFileName);
        string newFileNameExtension = System.IO.Path.GetExtension(newFileName);
        string newFilePath = System.IO.Path.Combine(fileInfo.Directory.FullName, newFileName);

        if (System.IO.File.Exists(newFilePath))
        {
            switch (fileExistBehavior)
            {
                case FileExistBehavior.None:
                    throw new System.IO.IOException("The destination file already exists.");

                case FileExistBehavior.Replace:
                    System.IO.File.Delete(newFilePath);
                    break;

                case FileExistBehavior.Rename:
                    int dupplicate_count = 0;
                    string newFileNameWithDupplicateIndex;
                    string newFilePathWithDupplicateIndex;
                    do
                    {
                        dupplicate_count++;
                        newFileNameWithDupplicateIndex = newFileNameWithoutExtension + " (" + dupplicate_count + ")" + newFileNameExtension;
                        newFilePathWithDupplicateIndex = System.IO.Path.Combine(fileInfo.Directory.FullName, newFileNameWithDupplicateIndex);
                    }
                    while (System.IO.File.Exists(newFilePathWithDupplicateIndex));

                    newFilePath = newFilePathWithDupplicateIndex;
                    break;

                case FileExistBehavior.Skip:
                    return;
            }
        }
        System.IO.File.Move(fileInfo.FullName, newFilePath);
    }
}

How to use this code

class Program
{
    static void Main(string[] args)
    {
        string targetFile = System.IO.Path.Combine(@"D://test", "New Text Document.txt");
        string newFileName = "Foo.txt";

        // Full pattern
        System.IO.FileInfo fileInfo = new System.IO.FileInfo(targetFile);
        fileInfo.Rename(newFileName);

        // Or short form
        new System.IO.FileInfo(targetFile).Rename(newFileName);
    }
}

In the File.Move method, this won't overwrite the file if it is already exists. And it will throw an exception.

So we need to check whether the file exists or not.

/* Delete the file if exists, else no exception thrown. */

File.Delete(newFileName); // Delete the existing file if exists
File.Move(oldFileName,newFileName); // Rename the oldFileName into newFileName

Or surround it with a try catch to avoid an exception.


NOTE: In this example code we open a directory and search for PDF files with open and closed parenthesis in the name of the file. You can check and replace any character in the name you like or just specify a whole new name using replace functions.

There are other ways to work from this code to do more elaborate renames but my main intention was to show how to use File.Move to do a batch rename. This worked against 335 PDF files in 180 directories when I ran it on my laptop. This is spur of the moment code and there are more elaborate ways to do it.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BatchRenamer
{
    class Program
    {
        static void Main(string[] args)
        {
            var dirnames = Directory.GetDirectories(@"C:\the full directory path of files to rename goes here");

            int i = 0;

            try
            {
                foreach (var dir in dirnames)
                {
                    var fnames = Directory.GetFiles(dir, "*.pdf").Select(Path.GetFileName);

                    DirectoryInfo d = new DirectoryInfo(dir);
                    FileInfo[] finfo = d.GetFiles("*.pdf");

                    foreach (var f in fnames)
                    {
                        i++;
                        Console.WriteLine("The number of the file being renamed is: {0}", i);

                        if (!File.Exists(Path.Combine(dir, f.ToString().Replace("(", "").Replace(")", ""))))
                        {
                            File.Move(Path.Combine(dir, f), Path.Combine(dir, f.ToString().Replace("(", "").Replace(")", "")));
                        }
                        else
                        {
                            Console.WriteLine("The file you are attempting to rename already exists! The file path is {0}.", dir);
                            foreach (FileInfo fi in finfo)
                            {
                                Console.WriteLine("The file modify date is: {0} ", File.GetLastWriteTime(dir));
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            Console.Read();
        }
    }
}

In my case, I want the name of the renamed file to be unique, so I add a date-time stamp to the name. This way, the filename of the 'old' log is always unique:

if (File.Exists(clogfile))
{
    Int64 fileSizeInBytes = new FileInfo(clogfile).Length;
    if (fileSizeInBytes > 5000000)
    {
        string path = Path.GetFullPath(clogfile);
        string filename = Path.GetFileNameWithoutExtension(clogfile);
        System.IO.File.Move(clogfile, Path.Combine(path, string.Format("{0}{1}.log", filename, DateTime.Now.ToString("yyyyMMdd_HHmmss"))));
    }
}

Examples related to c#

How can I convert this one line of ActionScript to C#? Microsoft Advertising SDK doesn't deliverer ads How to use a global array in C#? How to correctly write async method? C# - insert values from file into two arrays Uploading into folder in FTP? Are these methods thread safe? dotnet ef not found in .NET Core 3 HTTP Error 500.30 - ANCM In-Process Start Failure Best way to "push" into C# array

Examples related to file

Gradle - Move a folder from ABC to XYZ Difference between opening a file in binary vs text Angular: How to download a file from HttpClient? Python error message io.UnsupportedOperation: not readable java.io.FileNotFoundException: class path resource cannot be opened because it does not exist Writing JSON object to a JSON file with fs.writeFileSync How to read/write files in .Net Core? How to write to a CSV line by line? Writing a dictionary to a text file? What are the pros and cons of parquet format compared to other formats?

Examples related to rename

Gradle - Move a folder from ABC to XYZ How to rename a component in Angular CLI? How do I completely rename an Xcode project (i.e. inclusive of folders)? How to rename a directory/folder on GitHub website? How do I rename both a Git local and remote branch name? Convert row to column header for Pandas DataFrame, Renaming files using node.js Replacement for "rename" in dplyr Rename multiple columns by names Rename specific column(s) in pandas