Films Training Blog
Pipeline and Tools Characters
Pipeline and Tools Characters
search Login Join
favorite

Development Fund

Support Blender Core Development with a monthly contribution.

theaters

Blender Studio

The creators who share. Access production content and knowledge from the Open Movies.

code

Blender Developer Blog

Latest news and updates on Blender development.

people

Get Involved

Join the community and help with design, development, docs and more.

bar_chart

Open Data

A platform to collect and display the Blender Benchmark results.

menu_book

Blender Docs

Documentation on Blender's features, tools and API.

Blender Conference

The yearly event that brings together the Blender community in one place.

download

Get Blender

Download the latest Blender version, or try the beta!

Films
Training
Blog
Pipeline and Tools
Characters
Search
Login
Join

Course

Scripting for Artists
feed Course Overview
feed Blender Versions
Videos keyboard_arrow_down
  1. 01

    Introduction & copy-pasting

    Free
  2. 02

    Names & Objects

  3. 03

    Stuff on Lists

  4. 04

    Data Types

  5. 05

    Collections: Mass-Rename of Objects

  6. 06

    Blender Collections

    Free
  7. 07

    For vs. While

    Free
  8. 08

    Your Own Operator

    Free
  9. 09

    From Script to Add-on

    Free
  10. 10

    User Interfaces

    Free
  11. 11

    Custom Properties

    Free
  12. 12

    Asset Linking

    Free
  13. 13

    Roast my Add-on

    Free
  14. 14

    The Roast of Nature Clicker

    Free
  15. 15

    Modal Operators

    Free
  16. 16

    Readability & Understandability

Tech keyboard_arrow_down
  1. 01

    Updating F-Curves

  2. 02

    Render 10,000 OBJ files

  3. 03

    Mass-Rename Bones & Vertex Groups

  4. 04

    Rendering from 'all' angles

Course

Scripting for Artists
feed Blender Versions
Videos keyboard_arrow_down
  1. 01

    Introduction & copy-pasting

    Free
  2. 02

    Names & Objects

  3. 03

    Stuff on Lists

  4. 04

    Data Types

  5. 05

    Collections: Mass-Rename of Objects

  6. 06

    Blender Collections

    Free
  7. 07

    For vs. While

    Free
  8. 08

    Your Own Operator

    Free
  9. 09

    From Script to Add-on

    Free
  10. 10

    User Interfaces

    Free
  11. 11

    Custom Properties

    Free
  12. 12

    Asset Linking

    Free
  13. 13

    Roast my Add-on

    Free
  14. 14

    The Roast of Nature Clicker

    Free
  15. 15

    Modal Operators

    Free
  16. 16

    Readability & Understandability

Tech keyboard_arrow_down
  1. 01

    Updating F-Curves

  2. 02

    Render 10,000 OBJ files

  3. 03

    Mass-Rename Bones & Vertex Groups

  4. 04

    Rendering from 'all' angles

You need to login to view this content

You can join Blender Studio for €11.50/month and get access to all of our training & film content instantly!

Login Join Blender Studio

Videos

Collections: Mass-Rename of Objects

16th August 2017

info License: CC-BY
flag Report Problem

Published by

Sybren A. Stüvel

Learn about Collections in this video. Not only do we look more at lists, we also use dictionaries in order to automatically mass-rename objects in the scene, and tuples to assign to multiple names at the same time.

  • Use lists and dicts
  • Create your own function
  • Restructure your code after it works
  • Learn about tuples

Links from the video

  • Tuples

The Slides

Slides are only visible to Blender Cloud susbcribers

38 Comments

Join to comment publicly.

Julian Darley

9th November 2020 - 12:41

thank you, Sybren, for the suggestion (around 16:50) of using continue to avoid extra conditions and indenting. as an inexperienced python coder, this sounds like something that should be followed in all one's code. to this end, for anyone else struggling with the meaning of continue, what it really means in plain English is that the code will stop executing the current iteration of the loop and go back to the top of the loop process and move on to the next iteration, so continue means continue with the whole loop operation, rather than continue with this iteration. i found this very confusing at first.

Mark Jackson

14th April 2022 - 10:32

I love how with every video, your beard gets bushier

David mcsween

7th September 2017 - 10:49

Hmm, at 7.11'' I am confused by 'suflen'. How was this defined, I see that it was hard coded to 2 chars earlier. Is it a python function like 'len'?

Stephen Petersen

8th September 2017 - 09:53

@3pointedit: its defined in the code, suflen = len(suffix) so it should contain the length of what is in suffix. eg if suffix contain '_R' the suflen will equal 2 Hope I'm getting you question correct :)

Show more replies

David mcsween

11th September 2017 - 05:00

@Stefan59: Oh I see, does this mean that anything in a string after an underscore "_" is recognized as a suffix function? So "suffix" is a python tool? And is "some_name" also a python function as it doesn't get defined anywhere? I guess that it is a wildcard?

Stephen Petersen

11th September 2017 - 09:00

@3pointedit: Nope, i'm not great at explaining things so I hope you can understand. The suffix is a variable the script defines, it can be anything. In the tutorial suffix is computered to be either R_ or L_ as thats what we want to move, but really it can be any name or length. len(suffix) command just mean grab the length of suffix, adding suflen = len(suffix) defines suflen for the first time and gives it the value of the length of suffix, tutorial it is always 2 because R_ and L_ have the length of 2. You may need to do some python tutorials before try to understand python in blender, it will help. Steve

Sybren A. Stüvel

12th September 2017 - 12:20

@3pointedit: some_name is defined, it's the name of the first parameter of the rename function.

Whatever you pass as first parameter, it'll get the name some_name. For example, if you would call rename("steve", "L_"), it would act as if you had said some_name="steve" and suffix="L_".

David mcsween

13th September 2017 - 04:52

@Stefan59: Thank you for your patience :-) I think that I will have to rewatch some more times. How does the script calculate that the suffix (which is only a variable with no fixed length) is 2 characters long? Does it read the underscore or are you defining the suffix in ob.name?

Sybren A. Stüvel

13th September 2017 - 08:47

@3pointedit: There is less magic involved than that, the underscore is nothing special. This type of programming is called "imperative programming", which means that you tell the computer "do this, then do this, then do this". This means that len(suffix) is executed when the computer runs that bit of code. It doesn't matter that suffix can have different lengths at different times. The result of len(suffix) now is the length of suffix now. Try toying around with it in the interactive Python console.

Stephen Petersen

13th September 2017 - 08:49

@3pointedit: (5 minutes into tutorial) the function is defined def rename(some_name, suffix): and gets it value when called ob.name = rename(name, '_R')

so name is passed to some_name and '_R' is passed to suffix

David mcsween

14th September 2017 - 03:21

@Stefan59: Thank you, I guess I am getting lost on the order of operations/definitions?

Vincent Lamy

8th September 2017 - 14:16

Even after check python doc about tuples, I'm confuse about this line:

base_name, suffix = name[:-suflen], name[-suflen:]

I don't understand how the hell base_name find its value, and where is stored name[-suflen:]. In fact I just understand the part with suffix = name[:-suflen] :)

Vincent Lamy

8th September 2017 - 14:32

@vinc3r: Erf OK I got it, after relistening! (not native english speaker here).

I was thinking that suffix = name[:-suflen] but not!

For whose wondering:

base_name, suffix = name[:-suflen], name[-suflen:]

is equal to

base_name = name[:-suflen] and suffix = name[-suflen:]

Am i right ?

Show more replies

Sybren A. Stüvel

12th September 2017 - 12:16

@vinc3r: You're right, a, b = c, d is the same as a = c and b = d.

The added benefit of the former is that it also works when (c, d) is returned from a function, so then you can do a, b = function_returning_c_and_d().

Takeshi Funahashi

13th September 2017 - 14:06

I load some objs, then hope to add "test" for each cube name, in the scene, I code like that.

for ob in bpy.data.objects: ob.name = 'test' + ob.name

but it not work, eg cube001 change name 'testtesttesttestcube001" etc it added multiple "test" about each obj. I understand, something wrong, but could you teach me clear?

Sybren A. Stüvel

13th September 2017 - 14:40

@fun2tax: This is quite subtle. It happens because you're modifying the bpy.data.objects collection while you're looping over it. Internally Blender uses the object name to put the object into that collection. Since you're changing the keys, you're changing the collection itself, which causes objects to be visited more than once.

You can solve this by first creating a dictionary of new names, and then loop over that to give each object its new name:

new_names = 
for ob in bpy.data.objects:
    new_names[ob] = 'test' + ob.name
for ob, new_name in new_names.items():
    ob.name = new_name

This way you do not change bpy.data.objects in the first loop, and you do not change new_names in the second loop.

Show more replies

Takeshi Funahashi

13th September 2017 - 14:56

So I check list, in python doc, then change , as same as you did. for name, ob in bpy.data.objects.items():
ob.name = 'test_' + ob.name

it worked but the 'name' should be ob.name, is not it? actually even though I simply use name = 'test_' + name, all cube change name .

Takeshi Funahashi

13th September 2017 - 15:02

@sybren: thanks to take your time. I will try again your discribed code.

Takeshi Funahashi

13th September 2017 - 15:49

@sybren: Thanks I could understand better. so to chane obj.name in same loop need to use items()?

<code>for name, obj in bpy.data.objects.items(): if obj.location.x < 0: obj.name = 'Left_' + obj.name else: obj.name = 'Right_' +obj.name</code>

Sybren A. Stüvel

14th September 2017 - 14:36

@fun2tax: My point is that you do not want to use one loop. Loop 1: given the object, figure out its new name. Loop 2: given the new names, assign them to the objects. Combining those in a single loop is not possible, as you should not modify the collection you're looping over.

Takeshi Funahashi

15th September 2017 - 03:41

@sybren: Thanks, one thing I still can not understand is, why I can change key values when I use "items()"? <quote>for ob_name, ob in bpy.data.objects.items(): ob.name = "aaa_" + ob.name</quote>

this code seems work for me. but it not recommended?

Takeshi Funahashi

15th September 2017 - 05:24

or I can use values(), and keys() in spite of items()

 for ob in bpy.data.objects.values():
    ob.name = "aaa_" + ob.name   

for name in bpy.data.objects.keys():
    new_name = "aaa_" + name
    bpy.data.objects[name].name = new_name

but

 for obj in bpy.data.objects:
    obj.name = "aaa_" + obj.name

directly change bpy.data.objects collection keys , in this loop, then it can not work?

Takeshi Funahashi

15th September 2017 - 05:48

Have blender 2.79 current build change about it? because, now it seems work , even though I use

for obj in bpy.data.objects:
obj.name = "aaa_" + obj.name

when I test same thing in 2.79 rc2, it actually added many "aaa_" about same objects . but I may prefer your recommend way, which make new dictionary for new name, then use two loop without change collection in one loop. thanks.

Sybren A. Stüvel

15th September 2017 - 10:30

@fun2tax: Doing something the correct way is always preferrable to "it seems to work in this particular version of Blender" ;-)

Takeshi Funahashi

16th September 2017 - 05:30

@sybren: I could understand why it may cause problem by your answer. I just need to make it as habit, dividing 2 loop. ;-)

Pranavjit Virdi

1st September 2018 - 20:17

my rename and flip script, even after copy pasting from the slides does not seem to work, it changes the name but one of the objects out of two has a .001 at the end of of it, meaning that it changed the name of .l object into .R first but since .R object already existed blender added a .001 next to it, then it moves on the .R into .L and that seems to work. But the objects dont flip at all! and somehow this is working in your demonstration!.

Pranavjit Virdi

1st September 2018 - 20:21

@Pranavjit Virdi: ohkay sorry, so the script that i was refferring to at 13:02 works only if the names of the objects are not the same, meaning that it would work if you have a cube_L and sphere_R but it would not work if you have Cube_L and Cube_R, huh interesting, since the flip name solutions before that in the video seemed to work without error on just that scenario.

Show more replies

Sybren A. Stüvel

1st September 2018 - 22:11

@Pranavjit Virdi: In such cases having an intermediary name can help out. For example, first you rename Cube_L → Cube_L_becomes_R and Cube_R → Cube_R_becomes_L. Then rename them again, Cube_L_becomes_R → Cube_R and Cube_R_becomes_L → Cube_L. Then you're sure that you don't get any naming collissions.

Pranavjit Virdi

2nd September 2018 - 19:27

@Sybren A. Stüvel: _L_becomes_R is way more characters than suflen 2 which is already predefined, so i made it _E and _W (for east and west) but now it changes them to _E and _W only and i have to run the script another time for the _E to change to _L(which is what it was in the first place). another thing, even if i change the other object to have a different name the flipping of location doesn't work.

Pranavjit Virdi

2nd September 2018 - 20:55

@Pranavjit Virdi: alright the flipping does work now(i am often amazed at my stupidity, the objects i tested were spread along the y axis instead of the x axis.) the rest of the prob still stands.

Pranavjit Virdi

4th September 2018 - 21:46

@Pranavjit Virdi: k it works... here is the code if anyone wants to see it.

import bpy

suffix_translations = {
    '_R': '_E',
    '_L': '_W',
}
suflen = 2  # all suffixes should be this length.
for name, ob in bpy.data.objects.items():
    suffix = name[-suflen:]

    if suffix in suffix_translations:
        new_suffix = suffix_translations[suffix]
        ob.name = name[:-suflen] + new_suffix

        ob.location.x *= -1

suffix_translations_b = {
'_E': '_L',
'_W': '_R',
}

for name, ob in bpy.data.objects.items():
    suffix_b = name[-suflen:]
    if suffix_b in suffix_translations_b:
        new_suffix_b = suffix_translations_b[suffix_b]
        ob.name = name[:-suflen] + new_suffix_b

Pranavjit Virdi

4th September 2018 - 21:53

@Pranavjit Virdi: wow i just realized you addressed this issue in the video completely, i had paused the video before that point and didn't bother to see the whole thing through, hehe.

Lino Grandi

4th September 2018 - 10:26

Thanks for those amazing videos! I have a question about bones. I'd like to get the info of all currently selected bones and use an array to store their names, so I can then change them. Is there a way to do that using Python? Thanks!

Peter Smith

1st August 2019 - 15:31

Can someone help me out with why this code isn't working? I have a loop creating 20 Suzannes:

bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete()

for index in range(20):
    x = index % 4
    y = index // 4
    bpy.ops.mesh.primitive_monkey_add(size=0.2, location=(x,y,1))
    ob = bpy.context.active_object
    ob.name = 'Suzanne.R.' + str(f'{index+1:03}')
    ob.data.name = ob.name

Okay, markdown doesn't seem to like the { character in the code above (at least in the preview window) and is adding

Sybren A. Stüvel

2nd August 2019 - 22:17

*@Peter Smith* Well at least use f 'Suzanne.R.{index+1:03}' ;-) bpy.ops.mesh.primitive_monkey_add() creates a new monkey every time, so Blender will just keep making new ones. Since they are all in the same blend file, they have to have a unique name.

Peter Smith

4th August 2019 - 17:30

*@Sybren A. Stüvel* Thanks for the reply, but I don't think I was clear in my original question about what my issue is. The script deletes every object in the scene before then creating 20 monkey objects. The monkeys are renamed at object level (ob.name = str(f...) and that part works fine.

But when I then try to set the mesh data name to be the same as the object name (ob.data.name = ob.name) it doesn't work. It works the first time I run the script when I open Blender (i.e. in a new Blender session). But every time I run it after that the mesh data doesn't take the name of the object data. Instead, the mesh numbers are incremented, so by the time I've run the script a few times I end up with objects named e.g. Suzanne.R.001 but with mesh name Suzanne.R.240.

I don't get why that should be the case when the script deletes all the objects before recreating them? Is Blender somehow not "flushing out" the mesh data names when objects are deleted?

Sybren A. Stüvel

7th August 2019 - 13:51

*@Peter Smith* You're right, take a look at bpy.data.meshes. It does not remove those when you remove the objects. If you want to remove a mesh, use bpy.data.meshes.remove(the_mesh).

BTW, the str() call is unnecessary, as f"..." is already a string.

Peter Smith

7th August 2019 - 17:30

*@Sybren A. Stüvel* Cool, thanks for the reply, and thanks for the Python tip!

Blender Studio

The Creators Who Share.

Facebook Logo Twitter Logo YouTube Logo
  • Films
  • Blog
  • Training
Pipeline and Tools
  • Cloud Rig
  • Blender Kitsu
  • Contact Sheet Add-on
  • Blender Purge
  • Blender Cloud Services
Characters
  • Einar
  • Security Bot
  • Huginn
  • Pack Bot
Studio
  • Terms & Conditions
  • Privacy Policy
  • Contact
  • Remixing Music
  • Blender.org
Loading...