\$\begingroup\$
\$\endgroup\$
For web-uploading of Cyrillic-named images, I've written the script below:
#!/usr/bin/python
# coding=utf-8
import os
import argparse
import shutil
class Error: pass
class FolderError(Error): pass
def copytranstree (src, dst):
names = os.listdir( src )
try:
os.makedirs( dst )
except WindowsError:
pass
errors = []
for name in names:
srcname = os.path.join( src, name )
dstname = os.path.join( dst, ''.join([translit.get(x, x) for x in name.decode( input_parametres.encoding ).lower()]).encode( input_parametres.encoding ) )
try:
if os.path.isdir( srcname ):
copytranstree( srcname, dstname )
else:
shutil.copy2( srcname, dstname )
except (IOError, os.error), why:
errors.append( ( srcname, dstname, str( why ) ))
except Error, err:
errors.extend( err.args[0] )
try:
shutil.copystat( src, dst )
except WindowsError:
pass
except OSError, why:
errors.extend( (src, dst, str(why) ) )
if errors:
raise Error( errors )
parser = argparse.ArgumentParser(description='Copy directory tree with transliterated pathnames')
parser.add_argument('-e','--encoding', help='File system encoding', default='utf-8')
parser.add_argument('-s','--src', help='Source folder name', default='./' )
parser.add_argument('-d','--dst', help='Destination folder name', default='./')
input_parametres = parser.parse_args()
translit = dict(zip(u"абвгдеёзийклмнопрстуфхьъ", "abvgdeeziyklmnoprstufh'~"))
translit.update({u'ц': 'tz', u'ч': 'ch', u'ш': 'sh', u'ы': 'yi',
u'э': 'ye', u'ю': 'ju', u'я': 'ja', u' ': '_'})
src = os.path.abspath( input_parametres.src )
dst = os.path.abspath( input_parametres.dst )
if not os.path.exists( dst ):
dstname = ''.join([translit.get(x, x) for x in dst.decode( input_parametres.encoding ).lower()]).encode( input_parametres.encoding ).lower()
os.makedirs( dstname )
dst = os.path.abspath( dstname )
if not os.path.exists( src ) or os.path.isfile( dst ):
raise FolderError()
copytranstree( src, dst )
The script transliterates and copies a tree of files from a source folder to destination, considering encoding passed to the script (UTF for Ubuntu, CP121 for Windows).
Any ideas for common improvement of structure for Linux OS?
200_success
145k22 gold badges190 silver badges478 bronze badges
1 Answer 1
\$\begingroup\$
\$\endgroup\$
0
- All exceptions in python should inherit from an Exception class.
- WindowsError only works on Windows, its better to use the more general OSError
- You twice have a very long line to transliterate a string. Put it in a function and call it
- You should put any code that is part of the script proper in a main function.
- You shouldn't throw exceptions that you know won't be caught.
- The way you collect errors by throwing them up the stack is ugly.
- If you split the walking logic from the file operation logic the code will be clearer.
My updates (completely untested and probably wrong):
#!/usr/bin/python
# coding=utf-8
import os
import argparse
import shutil
class CommandError(Exception):
"""
Thrown when the user has made a mistake in the command line
"""
def transliterated_walk(encoding, src, dst):
"""
A generator which will walk over src producing them
along with the transliterated versions in dst
"""
files = []
for filename in os.listdir(src):
src_path = os.path.join(src, filename)
dest_path = os.path.join(dest, transliterated(encoding, filename))
if os.path.isdir(path):
for entry in transliterated_walk(encoding, src_path, dest_path):
yield entry
else:
files.append( (src_path, dest_path) )
yield src, dest, files
def copytranstree (encoding, src, dst):
errors = []
for src_path, dest_path, filenames in transliterated_walk(encoding, src, dest):
try:
os.makedirs( dest_path )
except WindowsError:
pass
for src_filename, dest_filename in filenames:
try:
shutil.copy2( src_filename, dst_filename )
except (IOError, os.error) as why:
errors.append( (src_filename, dest_filename, str(why) )
try:
shutil.copystat( src, dst )
except OSError as why:
errors.append( (src_path, dst_path, str(why) ) )
TRANSLIT = dict(zip(u"абвгдеёзийклмнопрстуфхьъ", "abvgdeeziyklmnoprstufh'~"))
TRANSLIT.update({u'ц': 'tz', u'ч': 'ch', u'ш': 'sh', u'ы': 'yi',
u'э': 'ye', u'ю': 'ju', u'я': 'ja', u' ': '_'})
def transliterate(encoding, string):
decoded = string.decode(encoding).lower()
transliterated = ''.join(translit.get(x, x) for x in decoded)
return transliterated.encode(encoding).lower()
def main():
try:
parser = argparse.ArgumentParser(description='Copy directory tree with transliterated pathnames')
parser.add_argument('-e','--encoding', help='File system encoding', default='utf-8')
parser.add_argument('-s','--src', help='Source folder name', default='./' )
parser.add_argument('-d','--dst', help='Destination folder name', default='./')
input_parametres = parser.parse_args()
src = os.path.abspath( input_parametres.src )
dst = os.path.abspath( input_parametres.dst )
if not os.path.exists( dst ):
dstname = transliterate(dst)
os.makedirs( dstname )
dst = os.path.abspath( dstname )
if not os.path.exists( src ):
raise CommandError('%s does not exist' % src)
if os.path.isfile( dst ):
raise CommandError('%s is a file' % dest)
copytranstree( encoding, src, dst )
except CommandError as error:
print error
if __name__ == '__main__':
main()
answered Apr 21, 2011 at 4:27
lang-py