Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python Python for File Systems Manipulation Consistency

Am I tackling this directory renaming problem correctly?

Prompt: Finish the function named cleanup in consistency.py. This function should take a string which will be a path to a local directory. The file names in this directory are messy. I need you to clean them up so they all follow the same pattern. Examples and further explanation are in the comments in the file below.

My code:

import os
import re
import dateutil.parser
import datetime


# Filenames consist of a username (alphanumeric, 3-12 characters)
# and a date (four digit year, two digit month, two digit day),
# and an extension. They should end up in the format
# year-month-day-username.extension.

# Example: kennethlove2-2012-04-29.txt becomes 2012-04-29-kennethlove2.txt

def cleanup(path):
    for name in os.listdir(path):
        # parse out username from file name
        username = re.search(r'[\w\d]*\d{3-12}', name).group()
        # parse out time from filename:
        re_time_search = re.search(r'\d{2,4}-\d{2,4}-\d{2,4}', name).group()
        # reformats parsed out time into YYYY-MM-DD format and save it as date variable
        date = dateutil.parser.parse(re_time_search).strftime('%Y-%m-%d')
        # parse out extension from file, alphanumeric allowed (.mp3, etc)
        ext = re.search(r'\.[\w\d]*', name).group()
        rename = date + '-' + username + '-' + ext
        os.rename(os.path.join(path, name), os.path.join(path, rename))

so my code lists the files in the path directory and parses out the username, date, and ext of the filenames, then renames them using the os.rename function.

The challenge returns the error AttributeError: 'NoneType' object has no attribute 'group' which means one of the re.search functions didn't find a match.

So my question is, do all the files in the directory have a username, date, AND extension? are there subdirectories in the directory?

Not sure what I'm doing wrong here... please help?

5 Answers

To better understand the problem I created a dummy directory (path) with a few dummy files (name). (Note: your datetime import is unused)

Your username parsing line is wrong. You can test it out on the string "kennethlove2-2012-04-29.txt" and you'll get zero matches. I found it was easier to use regex just for the date. Slicing is a much simpler way to find the extension and then the username.

Here's my working code, read all the comments:

# -*- coding: utf-8 -*-
"""
@author: Frederik Bussler
"""

import datetime
import os
import re

# Filenames consist of a username (alphanumeric, 3-12 characters)
# and a date (four digit year, two digit month, two digit day),
# and an extension. They should end up in the format
# year-month-day-username.extension.

# Example: kennethlove2-2012-04-29.txt becomes 2012-04-29-kennethlove2.txt

def cleanup(path):
    for name in os.listdir(path):
        # find the date in the pre-formatted file name
        orig_date = re.search(r'\d{4}-\d{2}-\d{2}', name)
        # format the date correctly
        formatted_date = datetime.datetime.strptime(orig_date.group(), '%Y-%m-%d').date()
        # the file extension is the last 4 characters (i.e. .txt)
        ext = str(name[-4:])
        # concatenate new string as date with a dash plus username plus extension
        # username is found by slicing name up to index of dash (start of date)
        new_str = str(formatted_date) + "-" + str(name[:name.index('-')]) + ext
        # rename files, make sure to join path with file name 
        os.rename(os.path.join(path, name), os.path.join(path, new_str))

That's pretty cool! Why can we use str(formatted_date) though? I thought we'd need to use strftime()

merc1er
merc1er
6,329 Points

Hi all!

Could you please let me know what is wrong with the following code (tested locally and worked but it won't work in the challenge):

import os

def cleanup(path):
    cdir = os.listdir(path)
    for f in cdir:
        name, ext = os.path.splitext(f)
        pseudo = name[0:-11:1]
        date = name[-1:13:-1][::-1] + '-'
        os.replace(f, date + pseudo + ext)

Thank you

Lawerence Lee
Lawerence Lee
19,912 Points

Things of note regarding this challenge:

  • The dates are indeed in YYYY-MM-DD format. If Kenneth had tried to trick you by including variants such as DD-MM-YYYY or MM-DD-YYYY, there wouldn't be any way for you to tell the difference between the formats. Case in point 12-11-2017 is valid for both variants I mentioned.
  • Using the RE library is allowed and worked for me.

TIP: Try and test your code using your terminal emulator (command line) and your actual file system.

  • Create a directory, you can delete it later.
  • Fill it with variations of both the correct and incorrect formatting.

    • You could do this with the following script:
    files = ['2012-04-29-kennethlove2.txt', 'kennethlove2-2012-04-29.txt', 
           'philip34king-1312-12-05.zip', 'osk18ear55-2354-12-08.jpeg']
    for a_file in files:
        os.system('touch {}'.format(a_file))
    
  • Provide the path to that directory as the argument for the cleanup function.

  • I'll leave the rest up to you...

I hate to say it, but Kenneth is really starting to annoy me big time!!! He's so confusing and I think he forgets some of us aren't like him. Anyway, here's my attempt: def cleanup(path): cdir = os.listdir(path) for f in cdir: name, ext = os.path.splitext(f) pseudo = name[0:-11:1] date = name[-1:13:-1][::-1] + '-' os.replace(f, date + pseudo + ext) So what's wrong with it???

def cleanup(path): cdir = os.listdir(path) for f in cdir: name, ext = os.path.splitext(f) pseudo = name[0:-11:1] date = name[-1:13:-1][::-1] + '-' os.replace(f, date + pseudo + ext)

files = ['2012-04-29-kennethlove2.txt', 'kennethlove2-2012-04-29.txt', 'philip34king-1312-12-05.zip', 'osk18ear55-2354-12-08.jpeg'] for a_file in files: os.system('touch {}'.format(a_file))files = ['2012-04-29-kennethlove2.txt', 'kennethlove2-2012-04-29.txt', 'philip34king-1312-12-05.zip', 'osk18ear55-2354-12-08.jpeg']

HELP ME!