Вопрос

[Edit: see final code below] I'm using the code below to randomly select 5 files from a source directory and then copy them to a new directory. It's giving me an IO error in which it says "No such file or directory 'x' exists" where "x" is the filename without the directory path. Somehow it isn't storing the path in "files." I looked on this forum as well as a shutil tutorial but I can't figure it out. (btw, this is similar to a previous question I asked but the code and error changed. I'll post the final code to that question when I get it working). Thanks in advance!

import os
import shutil
import random
import os.path

src_dir = 'C:\\'
target_dir = 'C:\\Test'
src_files = (os.listdir(src_dir))
def valid_path(dir_path, filename):
    full_path = os.path.join(dir_path, filename)
    return os.path.isfile(full_path)  
files = [f for f in src_files if valid_path(src_dir, f)]
choices = random.sample(files, 5)
for files in choices:
    shutil.copyfile(files, target_dir)
    print ('Finished!')
Это было полезно?

Решение

Try changing

shutil.copyfile(files, target_dir)

to

shutil.copyfile(os.path.join(src_dir, files), target_dir)

You're only using the src_dir to test whether the full path is valid, then you don't use it again.

Edit: Consider the following

src_dir = 'C:\\'
target_dir = 'C:\\Test'
# Create a list of filenames
src_files = (os.listdir(src_dir)) 
# Create a list of full paths (valid)
src_paths = [f for f in [os.path.join(src_dir, f) for f in src_files] if os.path.isfile(f)]
# Do selection
choices = random.sample(src_paths, 5)
for path in choices:
    print path
    shutil.copy(path, target_dir)
    print ('Finished!')

Note that I changed copyfile to copy since you were specifying a destination directory and not an destination file.

You could also add a leading r before your strings to make them raw strings to avoid having to escape the backslash:

dir = 'C:\\Temp\\' # Is the same as
dir = r'C:\Temp\'

But the SO syntax highlighter doesn't like it so I took it out

Другие советы

os.listdir() returns filenames only. You will need to use os.path.join() to join the path to them.

When you src_files = os.listdir(src_dir), you're getting just a list of filenames. You then enumerate [f for f in src_files if valid_path()], keeping just a list of filenames.

When you finally shutil.copyfiles(files, target_dir), you're still passing just the list of filenames, not the whole path.

files = [os.path.join(src_dir, f) for f in src_files if valid_path(src_dir, f)]

Here is the final code I ended up using. Thanks so much for your help!

import os
import shutil
import random
import os.path

src_dir = 'C:\\'
target_dir = 'C:\\TEST'
src_files = (os.listdir(src_dir))
def valid_path(dir_path, filename):
    full_path = os.path.join(dir_path, filename)
    return os.path.isfile(full_path)  
files = [os.path.join(src_dir, f) for f in src_files if valid_path(src_dir, f)]
choices = random.sample(files, 5)
for files in choices:
    shutil.copy(files, target_dir)
    print ('Finished!')
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top