This recipe (from Activestate) for Autodesk Autocad is a script which asks for a base directory and then changes all xrefs in all drawings in all subdirectories so that they use relative paths. To use it just copy it somewhere in your target directory structure and run.
# Relative-refs.pyw """A short python script for repathing xrefs in Autocad.""" import win32com.client,os, os.path, tkFileDialog from Tkinter import * from tkMessageBox import askokcancel from time import sleep # Get a COM object for Autocad acad = win32com.client.Dispatch("AutoCAD.Application") def repath(filename): print 'Repathing %s...' %filename doc = acad.Documents.Open(filename) blocks = doc.Database.Blocks # Internally xrefs are just blocks! xrefs = [item for item in blocks if item.IsXRef] if xrefs: for xref in xrefs: old_path = xref.Path new_path = os.path.join('..\\x-ref\\',os.path.basename(old_path)) xref.Path = new_path print 'Old path name was %s, new path name is %s.\n' %(old_path, new_path) try: doc.Close(True) # Close and save except: # Something when wrong, doc.Close(False) # close then report it raise class Logger: """A filelike object that prints its input on the screen.""" def __init__(self, logfile=None): """Takes one argument, a file like object for logging.""" print 'Starting logger...' if not logfile: self.logfile = open('relative-refs.log','w') else: self.logfile = logfile sys.stderr = self # Super cheap logging facility... sys.stdout = self # Just redirect output to a file. print 'Logger running...' def write(self, line): sys.__stdout__.write(line) self.logfile.write(line) def close(self): """The close method restores stdout and stderr to normal.""" self.logfile.close() sys.stderr = sys.__stderr__ sys.stdout = sys.__stdout__ class Tktextfile: """A file like interface to the Tk text widget.""" def __init__(self, root): """Create a scrollable text widget to be written to.""" self.root = root self.text = Text(root,width=40,height=20) self.text.pack(side=LEFT, expand=True, fill=BOTH) scrollbar = Scrollbar(root) scrollbar.pack(side=RIGHT,fill=Y) self.text.configure(yscrollcommand=scrollbar.set) scrollbar.config(command=self.text.yview) self.text.focus() def write(self, line): """Write method for file like widget.""" self.text.insert(INSERT, line) self.text.see(END) def close(self): """Fake close method.""" pass if __name__ == '__main__': if acad.Visible: acad.Visible = False root = Tk() text = Tktextfile(root) logger = Logger(text) dir = tkFileDialog.askdirectory() answer = askokcancel('RePath','Re path all dwg files in ' + dir + '?') if answer: for dirpath, subdirs, files in os.walk(dir): for name in files: ext = name.split('.')[-1] or '' # We want dwg files which are not in the x-ref directory if ext.lower() == 'dwg' and 'x-ref' not in dirpath.lower(): drawing = os.path.join(dirpath, name) try: repath(drawing) except: print 'Unable to repath drawing %s!' %drawing root.update() acad.Visible = True
There is also another example on Activestate, which casts Python objects as the correct Autocad type via win32com.client.CastTo(item)