# swap_link.py # Replace a link file with another one pointing to a new target # from pathlib import Path from os.path import relpath # won't be necessary with Python 3.12 thanks to walk_up arg in relative_to() def swap_link(lnk, tgt): #lnk: symbolic link to swap, str #tgt: target for new link, str lnpath = Path(lnk) if not lnpath.is_symlink(): raise Exception("First argument is not a symbolic link") elif lnpath.exists(): raise Exception("Link is not broken") tpath = Path(tgt) if tpath.is_symlink(): if not tpath.exists(): raise Exception("Target is also a broken link!") elif tpath.readlink().resolve() == lnpath.resolve() : raise Exception("Target is a link to link to be fixed...") tmp_suffix = 0 tmp_prefix = 'temp' tmp_name = tmp_prefix + str(tmp_suffix) tmp_path = Path(lnpath.parent / tmp_name) while tmp_path.exists() or tmp_path.is_symlink(): tmp_suffix += 1 tmp_name = tmp_prefix + str(tmp_suffix) tmp_path = Path(lnk.parent / tmp_name) sym_path = relpath(tgt, lnk)[3:] try: tmp_path.symlink_to(sym_path) except Exception: print(f"Attempted to create tmp link: {tmp_name}") raise Exception("Failed to create new symlink. Check permissions!") try: lnpath.unlink() except Exception: tmp_path.unlink() raise Exception("Failed to remove broken link. Check permissions!") tmp_path.rename(lnk)