I have the following two scripts. The first uses simple search/replace; the second uses regular expressions. You can set DRYRUN to see what it would do without actually doing it. == filesr {{{c #!/usr/bin/env python3 import sys,os import uuid,os.path args = sys.argv[1:] forreal = True if os.getenv("DRYRUN") is not None and os.getenv("DRYRUN") not in ["n","N"]: forreal = False elif os.getenv("D") is not None and os.getenv("D") not in ["n","N"]: forreal = False if len(args) < 3: print("filesr searchpat replpat ") sys.exit(1) s,r = tuple(args[:2]) files = args[2:] print(f"""filesrx search: {s} replace with: {r}""") def rn(x,y): if forreal: os.rename(x,y) while True: t = str(uuid.uuid4()) if not os.path.exists(t): break print("Temp name {}".format(t)) for x in files: y = x.replace(s,r) if x == y: pass elif os.path.exists(y): print("{} already exists".format(y)) else: xa = x.lower() ya = y.lower() if xa == ya: print("Capitalisation issue") print(f"Using temp name {t}: {x} --> {y}") rn(x,t) rn(t,y) else: print(f"Rename {x} --> {y}") rn(x,y) }}} == filesrx {{{c #!/usr/bin/env python3 import sys,os,re import uuid,os.path args = sys.argv[1:] forreal = True if os.getenv("DRYRUN") is not None and os.getenv("DRYRUN") not in ["n","N"]: forreal = False elif os.getenv("D") is not None and os.getenv("D") not in ["n","N"]: forreal = False if len(args) < 3: print("filesrx searchpat replpat ") print(" searchpad is regex") sys.exit(1) s,r = tuple(args[:2]) files = args[2:] print(f"""filesrx regex: {s} replace with: {r}""") sr = re.compile(s) def rn(x,y): if forreal: os.rename(x,y) while True: t = str(uuid.uuid4()) if not os.path.exists(t): break print("Temp name {}".format(t)) for x in files: try: y = sr.sub(r,x) except: print(f"Regex {s} failed for file {x}") continue print(f"{x} => {y}") if x == y: pass elif os.path.exists(y): print(f"{y} already exists") else: xa = x.lower() ya = y.lower() if xa == ya: print("Capitalisation issue") print(f"Using temp name {t}: {x} --> {y}") rn(x,t) rn(t,y) else: print(f"Rename {x} --> {y}") rn(x,y) }}}%TIME=1624658176