|
|
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.