Aug 102011

I’ve been working on a project that incorporates a lot of models that were made by duplicating or importing things into a scene over and over again. When this happens, you have lots of nodes that will have the same name, and Maya will differentiate between them by tacking the name of the parent onto the object using “|” as a separator (pCube1 becomes group1|pCube1, etc). For typical use, this isn’t a huge problem, but seeing as hardly any project I’ve worked on has been “typical” Maya use, duplicate object names end up breaking things more often than they don’t. This is especially apparent if you use a lot of custom scripts, which I do all the time.

I wrote a quick script to address this so that objects are always uniquely named. It works by analyzing all the transform nodes in your scene and looking for any names that contain ‘|’ which signifies that Maya found another object with the same name and is trying to differentiate them. After that, it renames any object it finds by tacking on a ‘_###’ string to the end, looking for the lowest possible number to use for ### in a while loop.

The biggest trick here was to make sure that I didn’t rename parent objects before I renamed their children. If I renamed ‘group1’ before I renamed ‘group1|pCube1’ then the latter object wouldn’t exist anymore by the time I got to it. To prevent this from happening, I built a dictionary where the key is the object’s full name, and the value is the number of times ‘|’ appears in the name. Then I sorted the dictionary by value (not by key) in reverse order, so that objects lowest in the hierarchy (the ones with the most ‘|’ characters) are renamed first.

The Python for that sorting looks like this:

badXforms = [f for f in if '|' in f]
    count = 0
    # we need to somehow sort this list by the number of '|' appearing in each name. this way we can edit names from the bottom of the hierarchy up,
    # and not worry about losing child objects from the list.
    countDict = {}
    for f in badXforms:
        countDict[f] = f.count('|')
    # now sort the dictionary by value, in reverse, and start renaming.
    for key,value in sorted(countDict.iteritems(),reverse=True, key=lambda (key,value): (value,key)):</pre>

The first line makes the list of all transforms that have ‘|’ in them. Then in the next few lines I build the dictionary so that when I sort the names by the ‘|’ count I know I’ll have all the original names in the right order.

The last line is the trickiest. You can get all the keys and values of a dictionary by saying this:

 for key,value in someDictionary.iteritems():

print key, value 

But I need this dictionary sorted by value, not by key, and I need it sorted backwards (in descending order). So I use the sorted() function on countDict.iteritems(), and add the flag reverse=True to sort descending. The last part just swaps keys and values of the dictionary for the purposes of the loop, without actually modifying the dictionary. Lambda functions are great for this sort of thing. lambda (key,value): (value,key)  is a very simple function that just reverses the two inputs.

I only just learned this trick, so I’m sorry if that didn’t make as much sense as it should have. Anyways, this script is really coming in handy on the job I’m working on right now, so I’m posting it up here (right click > Save As) for everybody else. To run the script, first initialize it in your Python window:

 import hf_renameDuplicates as hfRD 

Then to run the script:


Inside the parentheses you can use any number to determine the padding of the extension added to duplicate names. The default is 3.

Hope it’s useful!

  8 Responses to “Renaming duplicate nodes”

  1. Hi,

    I’d love to testdrive your scripts on a couple of bad assets here, but all of the download links seem to be broken, both at home and at my studio. In IE8 I get 404’s and in FF5 I get a 500 internal server error message. Is there an other way I could find access to your scripts? Thanks in advance!


    • you’re the second one to mention the scripts aren’t downloading… i’ll check this out tomorrow morning. thanks for letting me know!

    • Okay, I just double-checked… the links are working, but you need to right-click > Save As… to download the script. Because the file has a .py extension, your browser will try to ask my server to interpret the script instead of just saving it locally, so you have to make sure to save it. Let me know if you have any other problems.

      • Hi,
        The mel scripts download fine that way, but the python scripts remain elusive.
        When I Save Link As it downloads a file called But when I open that file in a text editor I get the html code for the error page I mentioned earlier,
        stating in the title block “500 Internal Server Error”.
        I wonder if zipping the python scripts would work, or renaming to .txt?…

        excerpt from the code I get in the file (without the html tags):
        “The server encountered an unexpected condition which prevented it from fulfilling the request.”
        “The script had an error or it did not produce any output. If there was an error, you should be able to see it in the error log.”


        • Thanks for bringing this to my attention! I just updated all the links with .ZIP files so the web server doesn’t try to compile them and break.

          • Wow thanks for the quick fix :)
            I’ll be testing (and learning, no doubt) tomorrow.
            The only file still being naughty is the IE8 and 9 give a 404, Chrome lets me download but winrar can’t open it. If I rename the .zip to .txt and open it directly in Notepad it gives 1 line reading “index.php”. I’d love to test drive the fixBadShaders script and learn what I can from it. So far your renderlayer breaking post has helped me and my team very much.

          • hey dennis,

            sorry about the mixup! everything is definitely working now. tried to do too many quick fixes on too little sleep. thanks for being patient.

  2. […] posts are: […]

Sorry, the comment form is closed at this time.