patternpythonMinor
Rename files to titlecased
Viewed 0 times
titlecasedfilesrename
Problem
I wrote this Python script to rename specified files to "titlecase", for example:
The main script:
``
hello.txttoHello.txt
hello there.txttoHello There.txt
path/to/file.txttopath/to/File.txt
The main script:
``
#!/usr/bin/env python
import os
import re
import argparse
re_junk = re.compile(r'[._-]')
re_spaces = re.compile(r'\s\s+')
def print_rename(old_filename, new_filename):
print('{} -> {}'.format(old_filename, new_filename))
def do_rename(old_path, new_path):
print_rename(old_path, new_path)
os.rename(old_path, new_path)
def get_new_path(old_path):
""" Get the new path, titlecased and (a little bit) sanitized.
- Only operate on the basename:
+ don't touch parent directories
+ don't touch the extension
- Sanitize:
+ replace junk characters with space
+ replace multiple spaces with single space
+ trim extra spaces at start and end
:param old_path: the path to rename
:return: titlecased and a little bit sanitized new path
"""
dirpart, filepart = os.path.split(old_path)
if filepart.startswith('.'):
return old_path
base, ext = os.path.splitext(filepart)
base = re_junk.sub(' ', base)
base = re_spaces.sub(' ', base).strip()
if not base:
return old_path
return os.path.join(dirpart, base.title() + ext)
def titlecase(old_path, fun):
if not os.path.exists(old_path):
return
new_path = get_new_path(old_path)
if old_path == new_path:
return
fun(old_path, new_path)
def main():
parser = argparse.ArgumentParser(description='Rename files to "titlecased" and "sanitized".')
parser.add_argument('-n', '--dry-run', action='store_true', help='Print what would happen, don\'t rename')
parser.add_argument('paths', nargs='+')
args = parser.parse_args()
fun = print_rename if args.dry_run else do_rename
for path in args.paths:
titlecase(path, fun)
if __name__ == '__main__':
main()
`Solution
-
I strongly oppose testing for file existence. It introduces a race condition: the path may exist at the time of test and disappear by the time of use; yes I am paranoid. Besides, it really impedes dry runs/unit testing - to try an interesting case you need to actually create a file. The pythonic way is to ask forgiveness, not permission:
Notice that it would also take care of other failures of
-
I am also not sure that "sanitization" is to be done unconditionally. A command line option would be nice.
-
Typically a debugging/diagnostic messages are sent to stderr. A
-
I strongly oppose testing for file existence. It introduces a race condition: the path may exist at the time of test and disappear by the time of use; yes I am paranoid. Besides, it really impedes dry runs/unit testing - to try an interesting case you need to actually create a file. The pythonic way is to ask forgiveness, not permission:
try:
os.rename(old_path, new_path)
except OSError:
pass # or an error messageNotice that it would also take care of other failures of
os.rename, such as new_path already exists or is too long; the directory is read-only, etc.-
I am also not sure that "sanitization" is to be done unconditionally. A command line option would be nice.
-
Typically a debugging/diagnostic messages are sent to stderr. A
quiet (or verbose) option is also desirable.-
fun doesn't strike as a particularly good name.Code Snippets
try:
os.rename(old_path, new_path)
except OSError:
pass # or an error messageContext
StackExchange Code Review Q#70024, answer score: 3
Revisions (0)
No revisions yet.