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