Created
January 23, 2016 13:54
-
-
Save billspat/9b57dc9a7643b63e87dd to your computer and use it in GitHub Desktop.
make os x files windows friendly
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# fix names | |
# toy program that looks for non-windows-friendly file names on an OS X system and emits "mv" commands to rename them. | |
# checks that files are uniquely named. Does not check for length of file path | |
# run the mv commands to make the changes | |
# TEST before using; no guarantees; in Public domain | |
import re | |
import os, sys | |
# | |
# illegal chars | |
# \ / : * ? " < > | | |
def fixpathname(pathname,replacechar = '_'): | |
"""given a path name (file or directory), replace all characters not whitelisted | |
with one replacement char, and make sure new name is unique so it won't clobber existing files | |
returns new name """ | |
newfname = pathname | |
pattern = re.compile('[^-.\w\s\(\)!\#$\&\{\},\~\+]') | |
if (pattern.search(pathname)): | |
# replace non-matching characters | |
newfname = pattern.sub(replacechar ,pathname) | |
# replace duplicates of these | |
newfname = re.sub(replacechar*2, replacechar,newfname) | |
newfname = re.sub(replacechar+" ", replacechar,newfname) | |
return(newfname) | |
def makeunique(fname, fnames): | |
"""given a filename and list of other filenames, make sure fname is unique and if not add a number""" | |
suffix = 0 | |
while fname in fnames: | |
suffix += 1 | |
root,ext = os.path.splitext(fname) | |
fname = "{1}_{0}{2}".format(suffix, root, ext) | |
return(fname) | |
def printfixes(f): | |
"""given dict of old and new names, print unix commands to rename it""" | |
for oldname, newname in f.iteritems(): | |
if oldname != newname: | |
print("mv \t\"{}\"\t\"{}\"".format(oldname,newname)) | |
def fixfolders(topfolder): | |
"""given a folder, walk tree and generate list of files/directories that need to be | |
renamed so that they are kosher on a windows system, then print list of comands to fix""" | |
# note full path is (os.path.join(root, name)) | |
# accumulators | |
filefixes={} | |
print "# --------- DIRECTORIES ---------" | |
dirfixes ={} | |
for root, dirs, files in os.walk(topfolder, topdown=False): | |
for dirname in dirs: | |
# dirpath = os.path.join(root, dirname) | |
if( dirname.startswith('.')): | |
pass # print('skipping {}'.format(dirpath)) | |
else: | |
newdirname = fixpathname(dirname) | |
if newdirname != dirname: | |
dirfixes[os.path.join(root, dirname)] = os.path.join(root, newdirname) | |
# create dict of current folder | |
newfilenames = {} | |
for fname in files: | |
newfilenames[fname] = fname | |
for fname in files: | |
# fix the name, if necessary | |
newfname = fixpathname(fname) | |
if newfname != fname: | |
# make sure it's not already in the folder listin | |
if newfname in newfilenames.values(): | |
newfname = makeunique(newfname,newfilenames.values()) | |
# update the curr dir list | |
newfilenames[fname] = newfname | |
# and add to global fix list | |
filefixes[os.path.join(root, fname)] = os.path.join(root, newfname) | |
printfixes(filefixes) | |
printfixes(dirfixes) | |
if __name__ == '__main__': | |
if len(sys.argv) < 2: | |
sys.exit('Usage: %s foldername' % args[0]) | |
fixfolders(sys.argv[1]) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# test_fixnames.py | |
# a few tests of file renaming using standard python unittest | |
import unittest | |
from fixnames import * | |
class TestFixNames(unittest.TestCase): | |
def test_fixonefile(self): | |
badfilename="a_B?c-d.txt" | |
fixedfilename="a_B_c-d.txt" | |
self.assertEqual(fixpathname(badfilename), fixedfilename) | |
def test_parens(self): | |
filename = "a (nice) file.txt" | |
# should not fix | |
self.assertEqual(fixpathname(filename), filename) | |
def test_okchars(self): | |
filename = "ok characters are -.()!#$&{},~+.xyz" | |
self.assertEqual(fixpathname(filename), filename) | |
def test_badchars(self): | |
# filename = 'bad characters are \-/-:-*-?-\'-\"-<->-|.xyz' | |
# fixed = 'bad characters are _-_-_-_-_-_-_-_-_-_.xyz' | |
badchars = "@/:*?\'\"<>|" | |
template = 'fileXname.txt' | |
for c in badchars: | |
filename = re.sub('X',c,template) | |
fixedname = re.sub('X','_',template) | |
# concept - loop through bad chars to test them | |
self.assertEqual(fixpathname(filename), fixed) | |
def test_fixsomefiles(self): | |
desiredfilenames = {'ok.txt': 'ok.txt', | |
'ok-with-dashes.txt': 'ok-with-dashes.txt', | |
'ok,with, commas.txt':'ok,with, commas.txt', | |
'ok with & ampsersands.txt':'ok with & ampsersands.txt', | |
'not?ok$.txt': 'not_ok$.txt', | |
'ok with spaces.txt': 'ok with spaces.txt' } | |
fixedfilenames = fixfiles(desiredfilenames.keys(),{}) | |
# original names stay the same... | |
self.assertEqual( set(desiredfilenames.keys()), set(fixedfilenames.keys())) | |
# and each one is fixed | |
for f in desiredfilenames.keys(): | |
self.assertEqual( fixedfilenames[f],desiredfilenames[f]) | |
# def test_folderfix(self): | |
# """concept for a test of real folder""" | |
# | |
# create temp dir testfolder=/tmp/randomfolder | |
# os.mkdir(path) | |
# add files to it from the desiredfilenames using touch | |
# | |
# result = fixfolder([testfolder]) | |
# use this to debug the test suite is working | |
# def test_that_fails(self): | |
# self.assertEqual(fixpathname('abc.txt'), 'nothin') | |
def test_folder(self): | |
fixfolders("~/tmp") | |
if __name__ == '__main__': | |
unittest.main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment