shutil is not moving all files

1.1k views Asked by At

I have a folder that has photos in it, and I would like to move the photos from that folder to another. The files:

IMAG_01.JPG
IMAG_02.JPG
IMAG_03.JPG
IMAG_04.JPG
IMAG_05.JPG
IMAG_06.JPG
IMAG_07.JPG
IMAG_08.JPG
IMAG_09.JPG

My code:

import os.path
import shutil
src = '/var/www/html/uploads/'
dst = '/media/pi/external/Photos/'
num_files = len([f for f in os.listdir(src)])
print(num_files)
for x in range(num_files):
    print(x)
    picture = (os.listdir(src)[x])
    print(picture)
    shutil.move(src+picture,dst+picture)

When I run the code, it will take half of the files, and then gives me an index out of range error on picture = (os.listdir(src)[x]). The output follows:

12
0
IMAG_04.jpg
1
IMAG_07.jpg
2
IMAG_01.jpg
3
IMAG_02.jpg
4
IMAG_09.jpg
5
IMAG_08.jpg
6
Traceback (most recent call last):
  File "upload.py", line 11, in <module>
    picture = (os.listdir(src)[x])
IndexError: list index out of range

I understand that it is telling me that x is not in the list, but I do not understand why that is throwing, since it should just start at 0 and go to 8.

1

There are 1 answers

1
Martijn Pieters On BEST ANSWER

You are making things way too complicated. You are calling os.listdir() repeatedly, while moving files out. So your result list gets shorter and shorter each time.

You start out with 12 names, but once you moved one you now get only 11 names in the directory, then 10, and by the time your x value hits 6, there are only 6 names left with indexes 0 through to 5, so os.listdir()[x] fails with an IndexError exception.

You don't need a length, and you don't need to use range(). Call os.listdir() once, and loop over the results:

import os.path
import shutil

src = '/var/www/html/uploads/'
dst = '/media/pi/external/Photos/'

for picture in os.listdir(src):
    print(picture)
    shutil.move(os.path.join(src, picture), os.path.join(dst, picture))

Now you have one complete list of all the names at the start, and the for loop assigns those names one by one to the picture variable. That those names are moved out no longer matters, as we don't call os.listdir() again.