|
@@ -1,32 +1,60 @@
|
|
#!/usr/bin/env python
|
|
#!/usr/bin/env python
|
|
|
|
|
|
-import sys
|
|
|
|
|
|
+# Extracts a zip archive while converting file names from Shift-JIS encoding to UTF-8.
|
|
|
|
+#
|
|
|
|
+# Example:
|
|
|
|
+# python unzip-jp.py archive.zip
|
|
|
|
+#
|
|
|
|
+# Creates a directory `archive` and extracts the archive there.
|
|
|
|
+#
|
|
import zipfile
|
|
import zipfile
|
|
-import argparse
|
|
|
|
|
|
+import sys
|
|
|
|
+import os
|
|
|
|
+import codecs
|
|
|
|
|
|
-parser = argparse.ArgumentParser(description="accept to and from encodings")
|
|
|
|
-parser.add_argument('-O', metavar='decode', default="shift-jis")
|
|
|
|
-parser.add_argument('-I', metavar='encode', default="cp437")
|
|
|
|
-args, files = parser.parse_known_args();
|
|
|
|
|
|
+if len(sys.argv) < 2:
|
|
|
|
+ print('No archive name.')
|
|
|
|
+ print('')
|
|
|
|
+ print('Usage: unzip-jp archive [password]')
|
|
|
|
+ exit(1)
|
|
|
|
|
|
-def unzip(filename, encode, decode):
|
|
|
|
- code = 0
|
|
|
|
- with zipfile.ZipFile(filename) as myzip:
|
|
|
|
- for info in myzip.infolist():
|
|
|
|
- try:
|
|
|
|
- info.filename = info.filename.encode(encode, 'strict').decode(decode, 'strict')
|
|
|
|
- myzip.extract(info)
|
|
|
|
- except Exception as e:
|
|
|
|
- code = 1
|
|
|
|
- print("failed to extract {0}: {1}".format(info.filename, e))
|
|
|
|
- return code
|
|
|
|
|
|
+name = sys.argv[1]
|
|
|
|
|
|
-def main(files, encode, decode):
|
|
|
|
- code = 0
|
|
|
|
- for file in files:
|
|
|
|
- if unzip(file, encode, decode) == 1:
|
|
|
|
- code = 1
|
|
|
|
- return code
|
|
|
|
|
|
+if len(sys.argv) > 2:
|
|
|
|
+ password = sys.argv[2]
|
|
|
|
+else:
|
|
|
|
+ password = None
|
|
|
|
|
|
-if __name__ == '__main__':
|
|
|
|
- sys.exit(main(files, args.I, args.O))
|
|
|
|
|
|
+directory = os.path.splitext(os.path.basename(name))[0]
|
|
|
|
+
|
|
|
|
+if not os.path.exists(directory):
|
|
|
|
+ os.makedirs(directory)
|
|
|
|
+
|
|
|
|
+with zipfile.ZipFile(name, 'r') as z:
|
|
|
|
+ if password:
|
|
|
|
+ z.setpassword(password.encode('cp850','replace'))
|
|
|
|
+ for f in z.infolist():
|
|
|
|
+ bad_filename = f.filename
|
|
|
|
+ if bytes != str:
|
|
|
|
+ # Python 3 - decode filename into bytes
|
|
|
|
+ # assume CP437 - these zip files were from Windows anyway
|
|
|
|
+ bad_filename = bytes(bad_filename, 'cp437')
|
|
|
|
+ try:
|
|
|
|
+ uf = codecs.decode(bad_filename, 'sjis')
|
|
|
|
+ except:
|
|
|
|
+ uf = codecs.decode(bad_filename, 'shift_jisx0213')
|
|
|
|
+ # need to print repr in Python 2 as we may encounter UnicodeEncodeError
|
|
|
|
+ # when printing to a Windows console
|
|
|
|
+ print(repr(uf))
|
|
|
|
+ filename=os.path.join(directory, uf)
|
|
|
|
+ # create directories if necessary
|
|
|
|
+ if not os.path.exists(os.path.dirname(filename)):
|
|
|
|
+ try:
|
|
|
|
+ os.makedirs(os.path.dirname(filename))
|
|
|
|
+ except OSError as exc: # Guard against race condition
|
|
|
|
+ if exc.errno != errno.EEXIST:
|
|
|
|
+ raise
|
|
|
|
+ # don't try to write to directories
|
|
|
|
+ if not filename.endswith('/'):
|
|
|
|
+ with open(filename, 'wb') as dest:
|
|
|
|
+ dest.write(z.read(f))
|