newest file within the list is problematic. If you look at the output of ftp.dir() you will see a list of platform-specific lines. You will have to parse each line, in a way that is appropriate to that platform; and use that information to either sort the list or just keep track of the currently youngest item. In the course of doing that, you can simply discard items from the list that do not meet your specification using, perhaps, [I]something[/I].endswith('.jpa')

Once I saw tonyjv's better solution, I realized it can be simplified even more: There is no need to cast the digits to an int: The ISO 8601 format sorts correctly as a string. You can even leave the dash:

def key_part(x):
return x.strip(string.letters + string.punctuation)

I don't know if casting to an int after a replace costs more or less than comparing the strings. I'm sure it doesn't matter for this small problem

second: 'site-www.website' sorts after 'site-website' ... and I suspect that 'site' and 'website' are both stand-ins for actual strings that OP didn't choose to share (which is good: simplifies the question).

I actually saw the possibility, but thought that learning to sort numbers lexically would maybe confuse OP more if he has little experience. Also the numbers seem to be fixed place for negative indexing, so simple slice as key would suffice. I did not like so fixed and blind solution.

In your case, you don't want to actually print all the names, so the outer print function is not what you need. Tony used it to show that the data ended up correctly sorted

For the same reason, the join function is also not needed.

Any list is iterable, so the sorted function can be used to return a sorted list when given a list.

If you just chant sorted([I]somelist[/I]) then you get back a list that was sorted using the entire element as the key. That doesn't work for your case because the prefix part (site-xxx) would 'overpower' the date-time part

To avoid using the entire item as a key, you can pass a function that derives a key from the item. We have shown you several possible functions that will do the job on the data you gave as examples

lambda is syntactic sugar for a normal function definition. Programmers prefer short lambda functions because they are local, anonymous and scoped

(local): As you read the program, you can easily see exactly what was intended without hunting around for the function definition (assuming you can parse the lambda syntax of course) :icon_lol:

(anonymous): You don't need to remember its name and can't use it elsewhere

At lines 26 and 27, 35 and 36 you seem to be spinning your wheels by first doing a join, then a split. Why? I'm guessing it helps with newlines?? in which case explore the rstrip() string member function: Certainly easier to understand, probably more efficient. For instance, at line 32, you could say if y.match(x.rstrip()): and something similar at line 37. The strip functions come in three flavors: strip() operates on both ends, lstrip() and rstrip() on only the left or right end of the string respectively.

I was about to suggest using with statement to protect the ftp connection, but it turns out ftplib is too ancient to support it. Instead, to be nice to the server, you want to wrap the use of your ftp connection in try...finally blocks so even if something, ahem, exceptional happens, your clean up code is run:

ftp = None
try:
ftp = ftplib.FTP(ftpserver)
# ... all the work is done here
# the except block is optional, but often very helpful
except Exception,x
print "Yeek:",type(x),x
# the finally block is always run, even if an exception happens
finally:
if ftp:
ftp.close()
ftp.quit()

A meta comment on your comments: "Way overkill", though it isn't wrong, and may be good if it helps you keep track of things. However I do suggest that you use a single '#' for most comments; use normal capitalization, so the comments don't seem to YELL AT YOU; and almost always, put the comment either on a line by itself (as a comment about the next block of code), or only one or two spaces after the end of the line (as a comment about that line only). This is the way most of the rest of us do it. The rule of thumb is that your code should be so blindingly obvious that comments are not needed (self documenting code)... or if not, then a short comment to explain your trick or subtlety. After all, it is the code itself that does the work, so the code should be what your eye is naturally drawn to.

Finally, I want to remind you that you can keep DaniWeb a little cleaner and more functional and slightly boost the reputation of the folks who helped you if you hunt down the 'solved' link at the bottom of the page and click it... after the thread is indeed solved, of course. Only the OP (Original Poster) has access to that link/button.

Thanks. I def agree with your spinning the wheels comment, but Im sure my code will get cleaner over time. As for the comments this was purley just as a precaution in case I forget any of the commands of functions while I pick up the basics.