Skip to content
Advertisement

Using random and shutil to move files in loop in python

I have a small problem. I am trying to move 20×500 images in 20 predefined folders. I can make this work with just 500 random images and I have identified the problem; I draw 500 random files, move them and then it tries doing it again but since it doesn’t update the random list, it fails when it reaches an image that it thinks is part of the random group but it has already been moved and thus fails. How do I “update” the random list of files so that it doesn’t fail because I move stuff? The code is:

import os
import shutil
import random

folders = os.listdir(r'place_where_20_folders_are')
files = os.listdir(r'place_where_images_are')
string=r"string_to_add_to_make_full_path_of_each_file"

folders=[string+s for s in folders]

for folder in folders:
    for fileName in random.sample(files, min(len(files), 500)):
        path = os.path.join(r'place_where_images_are', fileName)
        shutil.move(path, folder)

Advertisement

Answer

I think the problem in your code is that the random.sample() method leaves the original files list unchanged. Because of this you have a chance of getting the same filename twice, but as you already moved it before you will have an error.

Instead of using sample you could use this snippet:

files_to_move = [files.pop(random.randrange(0, len(files))) for _ in range(500)]

This will pop (thus removing) 500 random files from the files list and save them in files_to_move. As you repeat this, the files list becomes smaller.

This answer was inspired by this answer to the question Random Sample with remove from List.

This would be used like this:

import os
import shutil
import random

folders = os.listdir(r'place_where_20_folders_are')
files = os.listdir(r'place_where_images_are')
string=r"string_to_add_to_make_full_path_of_each_file"

folders=[string+s for s in folders]

for folder in folders:
    files_to_move = [files.pop(random.randrange(0, len(files))) for _ in range(500)]
    for file_to_move in files_to_move:
        path = os.path.join(r'place_where_images_are', file_to_move)
        shutil.move(path, folder)
User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement