Python script to fix broken symlinks

Monday, Sep 26, 2011 4:47 pm
William Barnes

I recently added a new hard drive and reorganized my increasingly chaotic and whimsically named storage and backup partitions. In the process, I moved a folder containing hundreds of symlinks to a different drive resulting in hundreds of broken symlinks (I should have used rsync).

This script will repair symlinks after you’ve moved a folder. Change BASEDIR to the current location of your files and OLDBASE to where they used to be. For example, if you moved all your files from /mnt/Backup2 to /mnt/Backup2, then BASEDIR = ‘/mnt/Backup2’ and OLDBASE = ‘/mnt/Backup1’. If you want to test (to make sure it will do what you expect) then change DEBUG to True.

This script will only fix symlinks that point to files/directories within the BASEDIR.

  1. #!/usr/bin/env python
  3. import os
  5. # Configuration
  7. BASEDIR = '/mnt/NewStorage'
  8. OLDBASE = '/mnt/OldStorage'
  9. DEBUG = False # I recommend a test run first
  11. def relink(path):
  12. old_target = os.path.realpath(path)
  13. new_target = old_target.replace(OLDBASE,BASEDIR,1)
  14. if DEBUG:
  15. print "Relink: " + path + "\n\tfrom " + old_target + "\n\tto " + new_target
  16. else:
  17. os.remove(path)
  18. os.symlink(new_target,path)
  20. for root, dirs, files in os.walk(BASEDIR):
  21. for filename in files:
  22. fullpath = os.path.join(root,filename)
  23. if os.path.islink(fullpath):
  24. relink(fullpath)
  25. for dirname in dirs:
  26. fullpath = os.path.join(root,dirname)
  27. if os.path.islink(fullpath):
  28. relink(fullpath)

If you save the script as ~/ then run it with python ~/

  • Brilliant! You just saved me hours relinking folders nested inside a multitude of subfolders. You sir are my hero of the day.

  • d2

    Thanks! A few tweaks and I used this to rearrange things after recovering to a mountpoint left me with a scattered few thousand /mnt/root/* and /mnt/var/* symlinks.

  • Jay

    I recently reinstalled using a different username/home folder, which created a mixture of valid and invalid links inside my restored user data.  I added a simple test to prevent the code from recreating valid (unbroken) links.

      if old_target != new_target:
        if DEBUG:
          print “Relink: ” + path + “ntfrom ” + old_target + “ntto ” + new_target