Can imported assets be automatically renamed by script?

I’m trying to eliminate one small step in a process I repeat a lot as I update artwork: deleting old assets before I import replacements. Specifically, I’m importing images as sprites in a 2D project and I frequently reimport artwork to see updates in-game.

The idea was to use AssetPostprocessor.OnPostprocessSprites to look for " 1" in the AssetImporter.assetPath of a newly imported sprite. If present, delete the original with AssetDatabase.DeleteAsset and rename the new without " 1" using AssetDatabase.RenameAsset.

The trouble is RenameAsset can’t find the asset at assetPath:

using UnityEngine;
using UnityEditor;

public class SpriteRenamer : AssetPostprocessor
{
    void OnPostprocessSprites(Texture2D texture, Sprite[] sprites)
    {
        TextureImporter importer = (TextureImporter)assetImporter;
        
        //returns "Assets/foo.png"
        Debug.Log(importer.assetPath);
        
        //returns "The source asset could not be found"
        Debug.Log(AssetDatabase.RenameAsset(importer.assetPath, "bar.png"));
    }
}

Hardcoding the path gave the same result…

Debug.Log(AssetDatabase.RenameAsset("Assets/foo.png", "bar.png"));

…but helped me discover renaming DOES work if I’m not trying to rename the asset currently being imported / postprocessed.

In other words, the first time I import foo.png, renaming fails, but the second time (when the imported file is actually “foo 1.png”) the old foo.png is successfully renamed to bar.png.

OnPostprocessSprites claims to “get a notification when an texture of sprite(s) has completed importing” but it seems to me Unity is not actually done with the asset at that point since AssetDatabase can’t see it.

Are there any other ideas to accomplish this goal? Is there anything wrong with the script above?


Final code using the accepted answer to automatically overwrite existing sprites with the same name in the same location:

void OnPostprocessSprites(Texture2D texture, Sprite[] sprites)
{
    TextureImporter spriteImporter = (TextureImporter)assetImporter;
    
    //end of directory path, start of file name
    int fileNamePos = spriteImporter.assetPath.LastIndexOf("/");
    //end of file name, start of file extension
    int fileExtPos = spriteImporter.assetPath.LastIndexOf(".");
    
    //parent directory with trailing slash
    string filePath = spriteImporter.assetPath.Substring(0, fileNamePos + 1);
    //isolated file name
    string fileName = spriteImporter.assetPath.Substring(fileNamePos + 1, fileExtPos - filePath.Length);
    //extension with "."
    string fileExt = spriteImporter.assetPath.Substring(fileExtPos);
    
    //check if this asset should replace another ("name 1.ext" should replace "name.ext")
    if(spriteImporter.assetPath.EndsWith(" 1" + fileExt))
    {
        //file name without trailing " 1"
        string fileNameOld = spriteImporter.assetPath.Substring(fileNamePos + 1, (fileExtPos - filePath.Length) - 2);
        
        //move old asset to trash so new asset can have the same name
        AssetDatabase.MoveAssetToTrash(filePath + fileNameOld + fileExt);
        
        //non-empty string indicates failure
        if(AssetDatabase.RenameAsset(spriteImporter.assetPath, fileNameOld) != "")
        {
            //ILogger refreshLogger = ???
            //refreshLogger.logEnabled = false;
            
            //calls OnPostprocessSprites (for the 2nd time)
            AssetDatabase.Refresh();  //prints crash message to console
            
            //refreshLogger.logEnabled = true;
        }
        else //successful RenameAsset calls OnPostprocessSprites (for the 3rd time)
        {
            //clear Refresh's crash message and unfortunately the whole console
            //Debug.ClearDeveloperConsole();
        }
    }
    else
    {
        //finally do post-processing here
        Debug.Log("post-processing: "+spriteImporter.assetPath);
    }
}

There are a couple ways to deal with AssetDatabase.Refresh’s crash message, commented out in the code above. One temporarily disables the logger Refresh uses, but it’s not Debug.logger so I’m not sure how to get it. The other idea clears the whole console after Refresh which is probably worse, so for now I’m just dealing with a dirty console.

You might need to do AssetDatabase.Refresh or maybe AssetDatabase.ImportAsset (similarly textureImporter.SaveAndReimport).