shutil not storing path for random select/copy of files?
Question
[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!')
La solution
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
Autres conseils
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!')