C#でファイルの名前を変更する


633

C#を使用してファイルの名前を変更するにはどうすればよいですか?


ここで問題があることを付け加えたいと思います。特に比較を行って、ある場所から別の場所(ファイル名だけでなくディレクトリ)にファイルを移動する場合、ボリュームがジャンクションポイント...したがって、newnameがq:\ SomeJunctionDirectory \ hello.txtで、古い名前がc:\ TargetOfJunctionPoint \ hello.txt ...の場合、ファイルは同じですが、名前が異なります。
エイドリアンハム

回答:


967

System.IO.File.Moveを見て、ファイルを新しい名前に「移動」します。

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

12
このソリューションは、ファイル名が大文字と小文字のみが異なる場合は機能しません。たとえば、file.txtとFile.txt
SepehrM

2
@SepehrM、私は再確認したところ、私のWindows 8.1マシンで問題なく動作しました。
Chris Taylor

1
@SepehrM、私はそれをテストしませんでしたが、File.MoveではなくFileInfo.Moveを使用することを指すサンプルなので、それは何か関係があるのでしょうか?
Chris Taylor

2
@SepehrM Windowsファイルシステム名では、大文字と小文字が区別されません。File.txtとfile.txtは同じファイル名として扱われます。したがって、ソリューションが機能しないと言うのは私にはわかりません。機能していない正確に何をしていますか?
マイケル

4
@Michael、ファイルシステムは大文字と小文字を区別しませんが、ユーザーが入力した元の大文字と小文字でファイル名を保存します。SepehrMの場合、彼はファイルの大文字と小文字を変更しようとしましたが、何らかの理由で機能しませんでした。大文字と小文字を区別しないマッチングが機能していました。HTH
Chris Taylor


47

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

または、例外を回避するためにトライキャッチで囲みます。


20
この方法には十分注意してください。宛先ディレクトリとソースディレクトリが同じで、「newname」が実際には「oldFileName」の大文字と小文字を区別するバージョンである場合は、ファイルを移動する前に削除します。
Adrian Hum、2016年

1
また、単一のファイルパスを表す方法はいくつかあるため、文字列が等しいかどうかを確認することはできません。
Drew Noakes 2017

File.Moveに、ファイルを上書きできるようにするオーバーロードメソッドが追加されました-File.Move(oldPath、newPath、true)
Ella


34

追加するだけです:

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

31
eww ...ファイルをアセンブルする代わりに、Path.Combine()を使用してください。
Adrian Hum

20
  1. 最初の解決策

    System.IO.File.Moveここに投稿された解決策は避けてください(マークされた回答が含まれています)。ネットワークでフェイルオーバーします。ただし、コピー/削除パターンはローカルでもネットワークでも機能します。移動ソリューションの1つに従いますが、代わりにコピーに置き換えます。次に、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


8
Microsoft.VisualBasic.FileIO.FileSystem.RenameFileがFile.Moveを呼び出します。元のファイルを正規化し、引数に追加のエラーチェックを行うことに感謝します。ファイルが存在する、ファイル名がnullではない、などの場合はFile.Moveを呼び出します。
Chris Taylor

Copy()がすべてのファイルストリームをコピーしない限り(そうではないと思います)、削除/コピーを使用しないでください。少なくとも同じファイルシステムにとどまっている場合、Move()は単なる名前変更であり、すべてのファイルストリームが維持されると思います。
nickdu

「ネットワーク経由でフェイルオーバー」すると、コード時間の便宜のために、実際にはダウンロードとアップロードであるコピーと削除を行います。どのようなネットワークですか。Windows共有フォルダー(smb)、、またはその他すべてはftpssh許可されていない限り(たとえば、読み取り専用)、ファイルの移動/名前変更のためのコマンド/プリミティブがあります。
ニャー猫2012年9

16

これを新しいファイルとしてコピーしてから、System.IO.Fileクラスを使用して古いファイルを削除できます。

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

4
これを読んでいる人への注意:これはアンチパターンであり、ファイルが存在するかどうかのチェックとコピーの呼び出しの間で、ファイルが別のプロセスまたはOSによって削除または名前変更される可能性があります。代わりにtryキャッチを使用する必要があります。
user9993

ボリュームが同じ場合、移動は実際にディレクトリ情報レベルで名前変更を行うため、これもI / Oの大きな無駄になります。
Adrian Hum、2016年

私は何千ものファイルを処理していて、コピー/削除は移動よりも速いという印象を受けました。
Roberto

誰がどのようにこのようなアイデアを思いつくでしょうか。より速くても、少なくともディスクを殺害しています。質問で「名前を変更する」と言うことは、ローカルで名前を変更することを意味します。もちろん、パーティション間の移動は含まれません。
ニャー猫2012年

File.Moveを使用すると、UnauthorizedAccessExceptionに遭遇しましたが、このコピーと削除のシーケンスは機能しました。ありがとう!
Oliver Konig

6

注:このサンプルコードでは、ディレクトリを開いて、ファイル名に開き括弧と閉じ括弧を含む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 2013年

2
これは有効な例です。やりすぎかもしれませんが、要点は別です。+1
アダム

1
@Adam:それは、3年前にすでに与えられた答えの非常に具体的な実装です。それがどのように建設的であるかを見てはいけません。
Nyerguds 2013

@Nyergudsでは、「ポイントの横」の定義が異なります。これは主観的な用語であるため、驚くことではありません。
アダム

@Nyergudsそれがあなたにとって無関係であるならば、それはそれで結構です。「サンプル/サンプル」コードの「実際の」実装を見つけるのに役立つため、冗長性を好む人もいます。ファイル名を変更します。アダムが言ったように、それがポイントの外にある方法はかなり主観的です。なぜか絶対に客観的だと感じる。ああ、それぞれ自分自身に。いずれにせよ、入力ありがとうございます。
MicRoc 14

6

うまくいけば!それはあなたのために役立ちます。:)

  public static class FileInfoExtensions
    {
        /// <summary>
        /// behavior when new filename is exist.
        /// </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);
        }
    }

このコードの使い方は?

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

6

使用する:

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

5
これを行う場合は、何かを行う前に 'oldFilePath'が存在することを確認することをお勧めします。そうしないと、理由もなく 'newFilePath'が削除されます。
John Kroetch 14

それもコンパイルしますか(Using System.IO;)?
Peter Mortensen

3

私の場合、名前を変更したファイルの名前を一意にしたいので、名前に日時スタンプを追加します。このように、「古い」ログのファイル名は常に一意です。

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

2

移動は同じことをしています=古いものをコピーして削除します。

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

1
確かに、あなたが気にしているのが最終結果だけなら。内部的にはそれほどではありません。
マイケル

いいえ、移動は確実にコピーと削除を行いません。
ジムバルター2017年

1

自分に合ったアプローチが見つからなかったので、自分のバージョンを提案します。もちろん、入力、エラー処理が必要です。

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

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

0

イベントハンドラー内でファイルの名前を変更する必要があり、名前の変更を含むすべてのファイル変更がトリガーされ、ファイルの名前の変更を永久にスキップする必要がある場合に、次のようにして名前を変更する必要が生じました。

  1. コピーを作成する
  2. オリジナルを削除する
File.Copy(fileFullPath, destFileName); // both has the format of "D:\..\..\myFile.ext"
Thread.Sleep(100); // wait OS to unfocus the file 
File.Delete(fileFullPath);

誰かの場合に備えて、そのようなシナリオがあります;)


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

rename()関数はstdio.hヘッダーファイルで定義されています。ファイルまたはディレクトリの名前をoldnameからnewnameに変更します。名前の変更操作は移動と同じであるため、この機能を使用してファイルを移動することもできます。


ようこそ。この質問は、C#言語を使用してファイルの名前を変更することに関するものです。Cの標準ライブラリ(C#ではない)から何かを指摘することがどのように役立つかわかりません。
ジェフダムマイヤー

-10

C#に機能がない場合は、C ++または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);
    }
}

20
C#には、ファイルの名前を変更する機能があります。
アンドリュー・バーバー、

76
私は言葉が
Chris McGrath

ありがとう、これはまさに私が欲しかったものです。実行可能ファイルの自己名を変更できます。
ジェイク
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.