在C#中重命名文件

783

如何使用C#重命名文件?


2
我讨厌这里有一个问题,所有的解决方案都在这里,特别是如果你要进行比较并且正在将文件从一个位置移动到另一个位置(目录和文件名都要变),你应该知道卷可以是联接点...所以如果新名称是 q:\SomeJunctionDirectory\hello.txt,旧名称是 c:\TargetOfJunctionPoint\hello.txt ... 这些文件是相同的,但名称不同。 - Adrian Hum
20个回答

1205

请参考System.IO.File.Move,将文件重命名为新名称。

System.IO.File.Move("oldfilename", "newfilename");

23
当文件名仅在字母大小写上不同的情况下,此解决方案无法起作用。例如,file.txt 和 File.txt。 - SepehrM
3
@SepehrM,我刚刚仔细检查了一下,在我的Windows 8.1电脑上运行良好。 - Chris Taylor
3
Windows 文件系统名称区分大小写。File.txt 和 file.txt 被视为相同的文件名。因此,当您说解决方案不起作用时,我不确定您指的是什么。您到底做了什么事情,不能正常工作? - Michael
6
@Michael,文件系统不区分大小写,但它会以用户输入的原始大小写形式存储文件名。在SepehrM的情况下,他试图更改文件的大小写,但由于某种原因未能成功。不区分大小写的匹配是有效的。希望对您有帮助。 - Chris Taylor
3
提供给大家参考,如果文件名长度在旧的8.3字符限制内,并且区分大小写,则更改大小写时可能会遇到问题。 - PRMan
显示剩余13条评论

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

59
在File.Move方法中,如果文件已经存在,它不会覆盖该文件。而且它会抛出一个异常。
因此我们需要检查文件是否存在。
/* 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

或者用try catch语句包围它以避免异常。


29
使用这种方法时要非常小心......如果目标文件夹和源文件夹相同,并且“newname”实际上是“oldFileName”的大小写敏感版本,那么在移动文件之前就会被删除。 - Adrian Hum
2
你也不能仅仅检查字符串是否相等,因为有多种表示单个文件路径的方式。 - Drew Noakes
3
File.Move现在有一个重载方法,可以让你覆盖文件 - File.Move(oldPath, newPath, true)。 - Ella
@Ella,我在File.Move中没有看到第三个参数。 - RobertSF
1
@RobertSF 这是在 .Net Core 3.0 及更高版本中的 - https://learn.microsoft.com/en-us/dotnet/api/system.io.file.move?view=netcore-3.1#System_IO_File_Move_System_String_System_String_System_Boolean_ - Ella
1
@Ella 确实如此。很遗憾,它仍未包含在 .Net Framework 4.6.1 中。 - RobertSF

50

只需要添加:

namespace System.IO
{
    public static class ExtendedMethod
    {
        public static void Rename(this FileInfo fileInfo, string newName)
        {
            fileInfo.MoveTo(fileInfo.Directory.FullName + "\\" + newName);
        }
    }
}

然后...

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

... "\" + newName + fileInfo.Extension - mac10688
45
请使用Path.Combine()代替手动拼接文件路径。注意保持原意不变,让内容更易懂。 - Adrian Hum

39

您可以使用File.Move来完成此操作。


23
  1. 第一种解决方案

    避免使用这里发布的System.IO.File.Move解决方案(包括标记答案)。它在网络上失败。但是复制/删除模式在本地和网络上都可以工作。跟随其中一种移动解决方案,但将其替换为Copy。然后使用File.Delete删除原始文件。

    您可以创建一个Rename方法来简化它。

  2. 易用性

    在C#中使用VB程序集。 添加对Microsoft.VisualBasic的引用

    然后重命名文件:

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

    两者都是字符串。请注意,myfile具有完整路径。newName没有。 例如:

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

    C:\whatever\文件夹现在将包含b.txt


12
请注意,Microsoft.VisualBasic.FileIO.FileSystem.RenameFile会调用File.Move。除了对原始文件进行规范化和对参数进行一些附加错误检查,例如文件存在、文件名不为空等,它还会调用File.Move。 - Chris Taylor
除非Copy()复制所有文件流,我认为最好不要使用delete/copy。我假设Move(),至少在保持在同一文件系统时,只是一个重命名操作,因此所有文件流都将被维护。 - user4238474
如果它在网络上失败了,那么你将会复制并删除(实际上是下载和上传),这只是为了方便编码时间... 什么样的网络?Windows共享文件夹(smb)、ftpssh或者其他所有都有用于文件移动/重命名的命令/原语,除非不允许(例如只读)。 - Meow Cat 2012

17
您可以使用 System.IO.File 类将其复制为新文件,然后删除旧文件:
if (File.Exists(oldName))
{
    File.Copy(oldName, newName, true);
    File.Delete(oldName);
}

5
给所有阅读此文的人:这是一种反模式,文件在检查其是否存在和执行复制操作之间可能会被其他进程或操作系统删除或重命名。因此,你需要使用try catch语句来实现复制操作。 - user9993
如果卷相同,这也是I/O的巨大浪费,因为移动实际上会在目录信息级别上进行重命名。 - Adrian Hum
我正在处理数千个文件,而且有一种感觉是复制/删除比移动更快。 - Santos
任何人怎么会想出这样的主意呢?无论快慢,至少你不会毁坏磁盘。在问题中说“重命名”应该意味着本地重命名,当然不涉及跨分区移动。 - Meow Cat 2012
使用File.Move时遇到了UnauthorizedAccessException,但是复制和删除的这个序列起作用了。谢谢! - Oliver Konig

12
public void RenameFile(string filePath, string newName)
{
    FileInfo fileInfo = new FileInfo(filePath);
    fileInfo.MoveTo(fileInfo.Directory.FullName + "\\" + newName);
}

1
你能解释一下这与其他答案的不同或相关性吗? - Stefan
1
@Stefan,我刚刚将它变成了一个干净且可重复使用的方法。因此,您可以最小化依赖并使用它。 - Majedur

8

注意:在这个示例代码中,我们打开一个目录并搜索名称中带有括号的PDF文件。您可以检查和替换名称中的任何字符,或者只需使用替换函数指定一个全新的名称。

有其他方法可以从这段代码中进行更复杂的重命名,但我的主要意图是展示如何使用File.Move进行批量重命名。当我在我的笔记本电脑上运行它时,它对180个目录中的335个PDF文件起作用。这是即兴编写的代码,还有更复杂的方法可以实现它。

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();
        }
    }
}

3
那完全跟问题没有关系,问题已经在3年前得到了精确的回答。 - Nyerguds
3
这是一个有效的例子。可能有些过头,但并不离谱。+1 - Adam
1
@Adam:这是一个非常具体的实现,与三年前已经给出的答案完全相同,而且最初的问题并不涉及任何具体的实现。我不明白这样做有什么建设性的意义。 - Nyerguds
@Nyerguds,那么我们对“离题”有不同的定义,这并不奇怪,因为它是一个主观的术语。 - Adam
@Nyerguds 如果这对你来说不相关,那就没关系了。有些人喜欢冗长,因为它可以帮助他们找到“样例/示例”代码的“真实世界”实现。它会重命名文件。它是否无关紧要基本上就像Adam所说的那样,这是主观的。出于某种原因,你感觉它绝对客观。好吧,各有所好。无论如何,感谢你的意见。 - MicRoc

7

没有任何答案提到编写可单元测试的解决方案。您可以使用System.IO.Abstractions,因为它提供了一个可测试的包装器,用于对文件系统操作进行包装。使用它,您可以创建模拟文件系统对象并编写单元测试。

using System.IO.Abstractions;

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

这是经过测试的可用代码,用于重命名文件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接