【C#】ファイル名にサフィックスを追加する

最近同じ処理を同じ実装を何度も書いて面倒だったので実装をの事したいと思います。

ファイルで拡張子とファイル名の間にサフィックスを追加する処理を何度も何度も書いてる気がするのでいい加減記事にしようと思ったので書いた内容です。

あと、フォルダの末尾に連番を自動的に付与する処理も実装してみました。

確認環境

  • Windows
  • .NET8
  • VisualStudio 2022

FileUtilクラス

このクラスの機能は以下の通りです。

  • 1) あるファイルパスのファイル名の末尾に特定の文字を挟む
    • 例) Sample.txt → Sample_hoge.txt
  • 2) ファイルパス / ファイル名の末尾に重複しない最大値の数値を追加する
    • Sample.txt → Sample_10.txt
    • NNは4桁までの数字で、自動的に最大値付与する
    • Sample_25.txt という名前を指定した場合、連番を振る前の名前をベースに連番を提案します
public static partial class FileUtil
{
    /// <summary>
    /// 指定したファイルパスのファイル名の末尾にワードを付け加えます。
    /// </summary>
    public static string AddSuffix(string filePath, string word)
    {
        //
        // C:\Hoge\Foo.txt
        // ↓
        // C:\Hoge\Foo_word.txt
        //

        string pareintDir = Path.GetDirectoryName(filePath) ?? "";
        string fileName = Path.GetFileNameWithoutExtension(filePath);
        string ext = Path.GetExtension(filePath);
        return Path.Combine(pareintDir, $"{fileName}_{word}{ext}");
    }

    /// <summary>
    /// 指定したファイル名の末尾に数値を追加する。
    /// </summary>
    public static bool TryAppendNumber(string filePath, out string newFilePath)
    {
        filePath = GetBaseName(filePath); // 数値が追加される前の値を復元

        string result = "";
        for (int i = 1000; i > 0; i--)
        {
            string tempPath = AddSuffix(filePath, i.ToString());
            if (File.Exists(tempPath))
            {
                break;
            }
            result = tempPath;
        }
        newFilePath = result;
        return newFilePath != "";
    }

    /// <summary>
    /// <see cref="TryAppendNumber"/> で数値を追加する前のファイルパスを取得する。
    /// </summary>
    public static string GetBaseName(string filePath)
    {
        Match m = _match().Match(Path.GetFileNameWithoutExtension(filePath));
        if (!m.Success)
        {
            return filePath;
        }

        string pareintDir = Path.GetDirectoryName(filePath) ?? "";
        string fileName = m.Groups["name"].Value;
        string ext = Path.GetExtension(filePath);
        return Path.Combine(pareintDir, $"{fileName}{ext}");
    }

    [GeneratedRegex(@"^(?<name>.+)_\d{1,4}$")]
    private static partial Regex _match();
}

DirectoryUtil

ファイルと同じでフォルダパスやフォルダ名の末尾に数値を「フォルダ名_NN」というように追加します。

public static partial class DirectoryUtil
{
    /// <summary>
    /// 指定したフォルダ名の末尾に数値を追加する。
    /// </summary>
    public static bool TryAppendNumber(string dirPath, out string newDirPath)
    {
        string result = "";
        for (int i = 1000; i > 0; i--)
        {
            string tempPath = $"{dirPath}_{i}"; 
            if (Directory.Exists(tempPath))
            {
                break;
            }
            result = tempPath;
        }
        newDirPath = result;
        return newDirPath != "";
    }

    /// <summary>
    /// <see cref="TryAppendNumber"/> で数値を追加する前のファイルパスを取得する。
    /// </summary>
    public static string GetBaseName(string dirPath)
    {
        Match m = _match().Match(Path.GetFileNameWithoutExtension(dirPath));
        if (!m.Success)
        {
            return dirPath;
        }

        string pareintDir = Path.GetDirectoryName(dirPath) ?? "";
        string fileName = m.Groups["name"].Value;
        string ext = Path.GetExtension(dirPath);
        return Path.Combine(pareintDir, $"{fileName}{ext}");
    }

    [GeneratedRegex(@"^(?<name>.+)_\d{1,4}$")]
    private static partial Regex _match();
}

これで面倒が少し減ったかな、、、?