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

Thomas Smith
Thomas Smith
23,240 Points

This code works in PyCharm but not in the challenge.

I get an IndexError: out of range.

consistency.py
import os
# 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):
    filename = path.split('.')
    date = []
    for _ in filename[0].split('-'):
        try:
            date.append(str(int(_)))
        except ValueError:
            username = _
    extension = filename[1]
    return username + '-' + '-'.join(date) + '.' + extension

Is path only the messy filename or is it a path to a file in a local directory?

I've done some (ugly) code that works in PyCharm too - but I get a similar error - so I'm wondering whether path is what we both assumed? Maybe we need to strip out the messy filename first, i.e. start with everything after the last backslash?

For amusement, I'll attach my code - it's fairly horrible! :smile:

def cleanup(path):
    new_list = path.split('-')
    day_ext = new_list[3].split('.')
    ext = day_ext[1]
    day = day_ext[0]
    return new_list[1] + '-' + new_list[2] + '-'+ day + '-' + new_list[0] + '.' + ext

Nah - I lashed some working code together for that scenario too. Same issue.

4 Answers

Thomas Smith
Thomas Smith
23,240 Points

Okay there's probably a better way to do this, but this worked.

def cleanup(path):
    for f in os.scandir(path):
        if f.is_file():
            f = f.path.split('/')[1]
            filename = f.split('.')[0]
            extension = f.split('.')[1]
            date = []
            for _ in filename.split('-'):
                try:
                    int(_)
                    date.append(_)
                except ValueError:
                    username = _
            old_name = path + '/' + f
            new_name = path + '/' + '-'.join(date) + '-' + username + '.' + extension
            os.rename(old_name, new_name)

Glad the idea that path was a folder triggered you to look at an alternative solution.

Well done on finding a solution!

Good work!

I think that question could do with a little more clarity, if I'm honest. Although I've not seen the video so I lack the context the challenge is posed within.

Steve.

That '/' after the path was key for me. The path they provide is only the name with no slashes.

Chris Freeman
Chris Freeman
Treehouse Moderator 68,457 Points

Great Job figuring this out. A few comments on the your code:

  • os.scandir returns os.DirEntry objects. From the docs, f.path is f's "full path name: equivalent to os.path.join(scandir_path, f.name)". Since you already know path and f.name, recreating the full path then re-dissecting it seems redundant. You can start with f.name
  • using _ as a loop variable name usually means its thrown away. It's better to pick an actual variable name if you use it, such as, "date_segment"
  • Your code may fail if the username is all ints. Luckily the test data doesn't have this condition.
  • using os.path.join might be cleaner in creating the old and new names
  • using a regex test on the file name might be clear to detect if a username comes first: r'^(?P<username>[\w0-9]+)-(?P<date>\d+-\d+-\d+)(?P<ext>\.\w+)$'
Thomas Smith
Thomas Smith
23,240 Points

The IndexError implies that the list created by splitting at "." only contains one item, which is weird because the challenge specifies that the filename string being passed into the function has an extension.

In your code, you're returning something with the username first; that's what the filename came as. The username should be last, before the extension, shouldn't it? You've also got two dashes next to each other?

That won't solve the problem, I don't think.

Let me try your code in PyCharm ...

Your code drops the zero in the month too. Running:

print(cleanup("shunter-2012-04-29.exe"))

outputs

shunter-2012-4-29.exe

It should output

2012-04-29-shunter.exe

I think.

Ignore the "double dash" nonsense - I skim-read it and missed the join(). Derp!

I'm confused but am not sure what the question is asking. The parameter is a path to a local directory. There will be many files in that directory whose name structure needs to change.

We know how to manipulate the filename - we now need to use the passed-in path to access all the files in that directory to change the names.

I dunno how to do that - I've not done this course!

Steve.

Thomas Smith
Thomas Smith
23,240 Points

I'm confused as well. The challenge has us import the os library, but I don't see how that's supposed to be used when we're apparently just modifying a string.

I fixed the bugs you showed me, but of course it's still giving me an IndexError

def cleanup(path):
    filename = path.split('.')
    date = []
    for _ in filename[0].split('-'):
        try:
            int(_)
            date.append(_)
        except ValueError:
            username = _
    extension = filename[1]
    return '-'.join(date) + '-' + username + '.' + extension

I don't think it is about modifying a string.

I think that path is a location of a folder that contains a lot of files which need modifying.