Batch rename materials with file names of linked texture?

I need to rename materials to the file names of the linked texture excluding the extension. The original file is an imported .obj, there is one texture to each material, after the material name is changed and some model scaling, it’s then exported as .fbx

I basically need some python script that can call the name of the first texture in a material, below is my feeble attempt.

import bpy
for material in = "Some Python Magic"

Any and all help is appreciated.

I’m not at my computer right now , but I’m guessing you would have to do something similar to what you have already done to get the texture name in the second line to assign to the material.

import bpy, re
context = bpy.context

def get_base_name(full_name):
index = re.findall(r’\d+’, full_name)
base_name = full_name[:-len(index[-1])]
return base_name

sel_obs = context.selected_objects
link_from_obs = {get_base_name( for ob in context.view_layer.objects if ob not in sel_obs and ob.type == ‘MESH’}

for ob in sel_obs:
link_from_ob = link_from_obs[get_base_name(]
for i, slot in enumerate(ob.material_slots):
slot.material = link_from_ob.material_slots[i].material

I saw this in another post about renaming selected objects , although this script does reference the material from another object. Maybe modify it a little.

Thanks for the help!
I was able to put together a working script with the links provided, this will save me so much time.

import bpy
import os
# Set the material_index to 0 ( the first material )
bpy.context.object.active_material_index = 0
# Go through list of materials assigned to selected object
for material in
    material_index = bpy.context.object.active_material_index
    old_name =
        # Get its first material slot
        material = bpy.context.active_object.material_slots[material_index].material
        # Get the nodes in the node tree
        nodes = material.node_tree.nodes
        # Get a principled node
        principled = next(n for n in nodes if n.type == 'BSDF_PRINCIPLED')
        # Get the slot for 'base color'
        base_color = principled.inputs['Base Color'] #Or principled.inputs[0]
        # Get the link
        link = base_color.links[0]
        link_node = link.from_node
        # Rename the material to the image name excluding the extension = os.path.splitext( )[0]
        # Print the results
        print( "Material Old Name:", old_name, )
        print( "Material New Name:", )
        print( )
        print( 'not found' )
    # Add 1 to the material_index count ( move to the next material )
    bpy.context.object.active_material_index +=1
1 Like

Hi there, don’t suppose you could tell how I could get the script to work with a Diffuse BSDF shader instead of a Principled?



change this line:
principled = next(n for n in nodes if n.type == 'BSDF_PRINCIPLED')

to this (you can use its .type if you want, i’m not personally a fan of comparing magic strings):
principled = next(n for n in nodes if isinstance(n, bpy.types.ShaderNodeBsdfDiffuse)

you will also need to change principled.inputs['Base Color'] to principled.inputs['Color']

Amazing :+1:t2:Thank you.

Hello! Sorry for hijacking the old topic, but when trying to use this code, I’ve got following error

Traceback (most recent call last):
  File "\Text", line 8, in <module>
AttributeError: 'NoneType' object has no attribute 'name'
Error: Python script failed, check the message in the system console

I’m using 3.2, could that be a problem?