|
|
1.1.1.2 ! root 1: #!/usr/bin/env python 1.1 root 2: """ 3: Script to copy Atari files with (potentially) too long names from 4: source directory into target directory, using in latter file names 5: clipped to 8+3 characters. 6: 7: Clipping is done like Atari GEMDOS functions would do it, so that 8: those file names can then be moved/copied to Atari media from another 9: OS. 10: 11: If original long names work with Hatari GEMDOS HD emulation, the 12: clipped names should work with normal TOS on real harddisk (image)! 13: """ 14: import sys, os, shutil 15: 16: def debug(msg): 17: sys.stderr.write("%s\n" % msg) 18: 19: def error_exit(msg): 20: name = os.path.basename(sys.argv[0]) 21: debug("\nUsage: %s <source dir> <target dir>" % name) 22: debug(__doc__) 23: debug("ERROR: %s!\n" % msg) 24: sys.exit(1) 25: 26: newnames = {} 27: 28: def check_conflicts(srcdir, dstdir): 29: # how much to clip from paths 30: srcskip = len(srcdir)+1 31: dstskip = len(dstdir)+1 1.1.1.2 ! root 32: print("\nNames that aren't unique:") 1.1 root 33: conflicts = False 34: for key,names in newnames.items(): 35: if len(names) > 1: 36: conflicts = True 1.1.1.2 ! root 37: print("- %s: %s" % (key[dstskip:], [name[srcskip:] for name in names])) 1.1 root 38: if not conflicts: 1.1.1.2 ! root 39: print("- none, all OK!") 1.1 root 40: 41: def hash_names(original, newname): 42: if newname not in newnames: 43: newnames[newname] = [] 44: newnames[newname].append(original) 45: 46: def clip_name(name): 47: dot = name.rfind('.') 48: if dot >= 0: 49: base = name[:dot] 50: ext = name[dot+1:] 51: name = "%s.%s" % (base[:8], ext[:3]) 52: else: 53: name = name[:8] 54: # TODO: map non-ASCII characters 55: return name.upper() 56: 1.1.1.2 ! root 57: def dirs_last(path): ! 58: # order first by type, then (case-insensitively) by name ! 59: return (os.path.isdir(path), path.upper()) 1.1 root 60: 61: def convert_dir(srcdir, dstdir): 1.1.1.2 ! root 62: print("\n%s/ -> %s/:" % (srcdir, dstdir)) 1.1 root 63: try: 64: os.mkdir(dstdir) 65: except OSError: 66: debug("ERROR: directory creation failed, name conflict???") 67: return 68: # directory sorting requires full names 69: dircontents = [os.path.join(srcdir, x) for x in os.listdir(srcdir)] 1.1.1.2 ! root 70: for original in sorted(dircontents, key=dirs_last): 1.1 root 71: origname = os.path.basename(original) 72: clipname = clip_name(origname) 73: newname = os.path.join(dstdir, clipname) 74: hash_names(original, newname) 75: if os.path.isdir(original): 76: convert_dir(original, newname) 77: else: 1.1.1.2 ! root 78: print("- %s -> %s" % (origname, clipname)) 1.1 root 79: try: 80: shutil.copyfile(original, newname) 81: except IOError: 82: debug("ERROR: file copy failed, name conflict (with read-only file)???") 83: continue 84: shutil.copystat(original, newname) 85: 86: def main(args): 87: if len(args) != 3: 88: error_exit("too few arguments") 89: srcdir = args[1] 90: dstdir = args[2] 91: if not os.path.isdir(srcdir): 92: error_exit("source directory '%s' doesn't exist" % srcdir) 93: if os.path.isdir(dstdir): 94: error_exit("target directory '%s' exists, remove it to continue" % dstdir) 95: if srcdir[-1] == os.path.sep: 96: srcdir = srcdir[:-1] 97: if dstdir[-1] == os.path.sep: 98: dstdir = dstdir[:-1] 99: if dstdir.startswith(srcdir+os.path.sep): 100: error_exit("target directory '%s' is inside source directory '%s'" % (srcdir, dstdir)) 101: convert_dir(srcdir, dstdir) 102: check_conflicts(srcdir, dstdir) 103: 104: if __name__ == '__main__': 105: main(sys.argv)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.