Reputation: 159
I have spent considerable time on my below code but I just can't get it to work and I'm hoping someone can offer me some advice.
#Example Code
import os, datetime
source = "U://Working_Files"
nameList=["U://Working_Files".format(x) for x in ['Property','Ownership','Sold','Lease']]
def Rename_and_move_files():
for name in nameList:
path=os.path.expanduser(os.path.join("~",name))
dirList=os.listdir(path)
for filename in dirList:
filePath=os.path.join(path,filename)
modified_time=os.path.getmtime(name)
modified_date=datetime.date.fromtimestamp(modified_time)
correct_format=modified_date.strftime('%Y%m%d')
if os.path.isfile(filePath):
new_name = correct_format + '_' + filename
destPath=os.path.join(path, "superseded", new_name)
print destPath
os.rename(filePath, new_name)
Rename_and_move_files()
In each folder (Property
for example) I have a superseded
folder. My end goal is to rename each file that is in each directory to prefix the date (e.g. 2018010_Property_Export.dfb
) and then move it to the superseded
folder.
Property->
Property_Export.dfb
Property_Export.xls
Property_Export.shp
Supserdeded (This is a folder)
I am not sure how to rename each file in each folder and then move it to the superseded
folder. At the moment I think I'm trying to rename the filepath instead of the individual file names.
Upvotes: 1
Views: 2988
Reputation: 1121466
"U://Working_Files".format(x)
results in "U://Working_Files"
, because there is no placeholder ({}
) in the string. You should really use os.path.join()
to handle path building. Also, you should not double the /
forward slash (you probably confused that with the \\
being required in a Python string literal to produce a single backslash):
import os.path
source = "U:/Working_Files"
nameList = [os.path.join(source, name) for name in ['Property', 'Ownership', 'Sold', 'Lease']]
This is really the only logic mistake you have made; the rest of the code does work as designed. That said, there are a few things that can be improved.
Personally, I'd leave the work of putting the source directory name and the names of the subdirectories together, to the function loop. That saves you an extra loop when just setting up your configuration.
source = "U:/Working_Files"
nameList = ['Property', 'Ownership', 'Sold', 'Lease']
I'd not prefix directories with ~
; leave that to whomever configures the source
directory; they can specify ~/some_directory
or ~someuser/some_directory
as a path explicitly. The function should take arguments, not use globals, anyway. Besides, prefixing your directories with ~
would disallow the use of ~some_other_account_name
at the start of such a path.
I'd skip over anything that isn't a file early; no need to get the modified date for a directory, right?
The following will move any non-directory name out of the directory, into the subdirectory named superseded
:
import os
import os.path
import datetime
def rename_and_move_files(source, subdirs, destination_subdir):
"""Archive files from all subdirs of source to destination_subdir
subdirs is taken as a list of directory names in the source path, and
destination_subdir is the name of a directory one level deeper. All files
in the subdirectories are moved to the destination_subdir nested directory,
renamed with their last modification date as a YYYYMMDD_ prefix.
For example, rename_and_move_files('C:\', ['foo', 'bar'], 'backup') moves
all files in the C:\foo to C:\foo\backup, and all files in C:\bar to
C:\bar\backup, with each file prefixed with the last modification date.
A file named spam_ham.ext, last modified on 2018-01-10 is moved to
backup\20180110_spam_ham.ext.
source is made absolute, with ~ expansion applied.
Returns a dictionary mapping old filenames to their new locations, using
absolute paths.
"""
# support relative paths and paths starting with ~
source = os.path.abspath(os.path.expanduser(source))
renamed = {}
for name in subdirs:
subdir = os.path.join(source, name)
destination_dir = os.path.join(subdir, destination_subdir)
for filename in os.listdir(subdir):
path = os.path.join(subdir, filename)
if not os.path.isfile(path):
# not a file, skip to the next iteration
continue
modified_timestamp = os.path.getmtime(path)
modified_date = datetime.date.fromtimestamp(modified_timestamp)
new_name = '{:%Y%m%d}_{}'.format(modified_date, filename)
destination = os.path.join(destination_dir, new_name)
os.rename(path, destination)
renamed[path] = destination
return renamed
source = "U:/Working_Files"
name_list = ['Property', 'Ownership', 'Sold', 'Lease']
renamed = rename_and_move_files(source, name_list, 'superseded')
for old, new in sorted(renamed.items()):
print '{} -> {}'.format(old, new)
The above also tries to minimise work. You only need to resolve the source
path once, not for each name in subdirs
. datetime
objects support str.format()
formatting directly, so we can form the new filename in one step from the modified timestamp and the old name. The os.path.abspath()
cleans out errors like the //
double slash as well, making it more robust.
Rather than print each path in the loop, the function returns a mapping of files that have been renamed, so the caller can process that further as needed.
Upvotes: 3
Reputation: 2015
See if this below code will work for you. This code will go through all the working folders, find only the files, rename and move those renamed files to the superseded folder
import os
import shutil
working_folders = [f'C:\working_folders\{x}' for x in ['Property','Ownership','Sold','Lease']]
for wf in working_folders:
for f in os.listdir(wf):
if os.path.isfile(os.path.join(wf, f)):
os.rename(os.path.join(wf, f), os.path.join(wf, f'2018010_Property_Export.dfb_{f}'))
shutil.move(os.path.join(wf, f'2018010_Property_Export.dfb_{f}'), os.path.join(wf, 'superseded', f'2018010_Property_Export.dfb_{f}'))
Upvotes: -1