Python script
Change the path on line 3 src_file = "E:/tempmymat.blend"
import bpy
src_file = "E:/tempmymat.blend"
D = bpy.data
def main():
# find materials that you want to replace
bad_mats = {m.name:m for m in D.materials if not m.library}
# load materials to replace with
with D.libraries.load(src_file, link=True) as (src, me):
me.materials = [name for name in src.materials if name in bad_mats]
# create copies of the loaded file's materials, rename them and store
# a convenient dictionary pointing from old materials to new materials
replacements = {}
for m in me.materials:
new_mat = m.copy()
bad_mat = bad_mats[m.name]
new_mat.name = m.name
replacements[bad_mat] = new_mat
# find old materials and replace with new materials
for o in D.objects:
for slot in o.material_slots:
replacement = replacements.get(slot.material)
if replacement:
slot.material = replacement
# unlink old materials and the external file (library)
for m in bad_mats.values():
D.materials.remove(m)
D.libraries.remove(D.libraries[-1])
main()
if not m.library
is used on the first line of main()
in order to ensure there's a single material with each name. If you need to make it work with materials linked to other files also being replaced, remove that condition. If you're worried that as a result you can indeed get multiple materials with the same name in that dictionary, you need to come up with some other method of associating a loaded material with an existing material.
Related:
How to know which object is using a material
How can I replace a material from Python?
How to Link/Append a data-block using the Python API?