pythonpython-3.xlist-comprehensionfile-move

One-line "for" loop using list comprehension


Someone has challenged me to create a program that sorts their pictures into folders based on the month they were taken, and I want to do it in one line (I know, it's inefficient and unreadable, but I still want to do it because one-liners are cool)

I needed a for loop to accomplish this, but the only way I know of to use a for loop in one line is list comprehension, so that's what I did, but it creates an empty list, and doesn't print anything from the list or anything.

What I'm doing is renaming the file to be the month created + original filename (ex: bacon.jpg --> May\bacon.jpg)

Here is my code (Python 3.7.3):

import time
import os.path
[os.rename(str(os.fspath(f)), str(time.ctime(os.path.getctime(str(os.fspath(f))))).split()[1] + '\\' + str(os.fspath(f))) for f in os.listdir() if f.endswith('.jpg')]

and the more readable, non-list-comprehension version:

import time
import os.path
for f in os.listdir():
    fn = str(os.fspath(f))
    dateCreated = str(time.ctime(os.path.getctime(fn)))
    monthCreated = dateCreated.split()[1]
    os.rename(fn, monthCreated + '\\' + fn)

Is list comprehension a bad way to do it? Also, is there a reason why, if I print the list it's [] instead of [None, None, None, None, None, (continuing "None"s for every image moved)]?

Please note: I understand that it's inefficient and bad practice. If I were doing this for purposes other than just for fun to see if I could do it, I would obviously not try to do it in one line.


Solution

  • Is list comprehension a bad way to do it?

    YES. But if you want to do it in one line, it is either that or using ";". For instance:

     for x in range(5): print(x);print(x+2)
    

    And, by the way, just renaming a file including a slash will not create a folder. You have to use os.mkdir('foldername').

    In the end, if you really want to do that, I would just recommend doing it normally in many lines and then separating it with semicolons in a single line.