Dunuts
Dunuts

Reputation: 159

Renaming and Moving Files

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

Answers (2)

Martijn Pieters
Martijn Pieters

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

Satish Michael
Satish Michael

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

Related Questions