I have a folder with many subfolders that contains images. I want to copy these images of the subfolders to the destination folder. All images should be in one folder. With my current code, Python copies all subfolders to the destination folder, but thats not what I want. I only what the .jpg images. My current code is:
dir_src = r"/path/to/folder/with/subfolders"
dir_dst = r"/path/to/destination"
for file in os.listdir(dir_src):
print(file)
src_file = os.path.join(dir_src, file)
dst_file = os.path.join(dir_dst, file)
shutil.copytree(src_file, dst_file)
I'm grateful for every tip
You can use os.walk:
import os
from shutil import copy
dir_src = r"/path/to/folder/with/subfolders"
dir_dst = r"/path/to/destination"
for root, _, files in os.walk(dir_src):
for file in files:
if file.endswith('.jpg'):
copy(os.path.join(root, file), dir_dst)
or you can use glob if you're using Python 3.5+:
import glob
from shutil import copy
dir_src = r"/path/to/folder/with/subfolders"
dir_dst = r"/path/to/destination"
for file in glob.iglob('%s/**/*.jpg' % dir_src, recursive=True):
copy(file, dir_dst)
Related
I have 23000 files in one folder and want to copy files with their names ending with some specific text to other folder using python. I used the following code, though it runs successfully but it doesn't copy the file in the destination folder.
import os
import shutil
path = "D:/Snow_new/test"
outpath = "D:/Snow_new/testout"
for f in os.listdir(path):
if f.endswith("clip_2"):
shutil.copyfile(os.path.join(path, f), outpath)
you are trying to copy files to a single filename again and again, so to fix it you will have to add the filename with outpath for every file
import os
import shutil
path = "D:/Snow_new/test"
outpath = "D:/Snow_new/testout"
if not os.path.isdir(outpath):
os.mkdir(outpath)
else:
shutil.rmtree(outpath)
os.mkdir(outpath)
for f in os.listdir(path):
f2, ext = os.path.splitext(f)
if f2.endswith("clip_2"):
shutil.copyfile(os.path.join(path, f), os.path.join(outpath, f))
before running the above code make sure that you remove D:/Snow_new/testout completly
I have a folder with several sub-folders, each containing the same number of files (here it is 7). The code that I use at the present copies all the files from the different sub-folders within a main folder, to another new folder.
import os
import shutil
src = r'C:\Users\datasets\test\0'
dest = r'C:\Users\datasets\data_new\test\0'
for path, subdirs, files in os.walk(src):
for name in files:
filename = os.path.join(path, name)
shutil.copy2(filename, dest)
I need to modify the code in a way to copy only the last image (i.e. the 7th image in this case) from each sub-folder (windows file arrangement) to a new folder.
This should do it for you.
import os
import shutil
from glob import glob
src = r'C:\temp\datasets\test\0'
dest = r'C:\temp\datasets\data_new\test\0'
for base, dirs, _ in os.walk(src):
for path in dirs:
files = sorted(glob(os.path.join(base, path, '*')))
if len(files) == 0:
continue
file = files[-1]
filename = os.path.join(path, file)
shutil.copyfile(filename, dest)
I wrote down this code:
import shutil
files = os.listdir(path, path=None)
for d in os.listdir(path):
for f in files:
shutil.move(d+f, path)
I want every folder in a given directory (path) with files inside, the files contained in that folder are moved to the main directory(path) where the folder is contained.
For Example:
The files in this folder: C:/example/subfolder/
Will be moved in: C:/example/
(And the directory will be deleted.)
Sorry for my bad english :)
This should be what you are looking for, first we get all subfolders in our main folder. Then for each subfolder we get files contained inside and create our source path and destination path for shutil.move.
import os
import shutil
folder = r"<MAIN FOLDER>"
subfolders = [f.path for f in os.scandir(folder) if f.is_dir()]
for sub in subfolders:
for f in os.listdir(sub):
src = os.path.join(sub, f)
dst = os.path.join(folder, f)
shutil.move(src, dst)
Here another example , using a few lines with glob
import os
import shutil
import glob
inputs=glob.glob('D:\\my\\folder_with_sub\\*')
outputs='D:\\my\\folder_dest\\'
for f in inputs:
shutil.move(f, outputs)
I have the following directory structure:
-mailDir
-folderA
-sub1
-sub2
-inbox
-1.txt
-2.txt
-89.txt
-subInbox
-subInbox2
-folderB
-sub1
-sub2
-inbox
-1.txt
-2.txt
-200.txt
-577.txt
The aim is to copy all the txt files under inbox folder into another folder.
For this I tried the below code
import os
from os import path
import shutil
rootDir = "mailDir"
destDir = "destFolder"
eachInboxFolderPath = []
for root, dirs, files in os.walk(rootDir):
for dirName in dirs:
if(dirName=="inbox"):
eachInboxFolderPath.append(root+"\\"+dirName)
for ii in eachInboxFolderPath:
for i in os.listdir(ii):
shutil.copy(path.join(ii,i),destDir)
If the inbox directory only has .txt files then the above code works fine. Since the inbox folder under folderA directory has other sub directory along with .txt files, the code returns permission denied error. What I understood is shutil.copy won't allow to copy the folders.
The aim is to copy only the txt files in every inbox folder to some other location. If the file names are same in different inbox folder I have to keep both file names. How we can improve the code in this case ? Please note other than .txt all others are folders only.
One simple solution is to filter for any i that does not have the .txt extension by using the string endswith() method.
import os
from os import path
import shutil
rootDir = "mailDir"
destDir = "destFolder"
eachInboxFolderPath = []
for root, dirs, files in os.walk(rootDir):
for dirName in dirs:
if(dirName=="inbox"):
eachInboxFolderPath.append(root+"\\"+dirName)
for ii in eachInboxFolderPath:
for i in os.listdir(ii):
if i.endswith('.txt'):
shutil.copy(path.join(ii,i),destDir)
This should ignore any folders and non-txt files that are found with os.listdir(ii). I believe that is what you are looking for.
Just remembered that I once wrote several files to solve this exact problem before. You can find the source code here on my Github.
In short, there are two functions of interest here:
list_files(loc, return_dirs=False, return_files=True, recursive=False, valid_exts=None)
copy_files(loc, dest, rename=False)
For your case, you could copy and paste these functions into your project and modify copy_files like this:
def copy_files(loc, dest, rename=False):
# get files with full path
files = list_files(loc, return_dirs=False, return_files=True, recursive=True, valid_exts=('.txt',))
# copy files in list to dest
for i, this_file in enumerate(files):
# change name if renaming
if rename:
# replace slashes with hyphens to preserve unique name
out_file = sub(r'^./', '', this_file)
out_file = sub(r'\\|/', '-', out_file)
out_file = join(dest, out_file)
copy(this_file, out_file)
files[i] = out_file
else:
copy(this_file, dest)
return files
Then just call it like so:
copy_files('mailDir', 'destFolder', rename=True)
The renaming scheme might not be exactly what you want, but it will at least not override your files. I believe this should solve all your problems.
Here you go:
import os
from os import path
import shutil
destDir = '<absolute-path>'
for root, dirs, files in os.walk(os.getcwd()):
# Filter out only '.txt' files.
files = [f for f in files if f.endswith('.txt')]
# Filter out only 'inbox' directory.
dirs[:] = [d for d in dirs if d == 'inbox']
for f in files:
p = path.join(root, f)
# print p
shutil.copy(p, destDir)
Quick and simple.
sorry, I forgot the part where, you also need unique file names as well. The above solution only works for distinct file names in a single inbox folder.
For copying files from multiple inboxes and having a unique name in the destination folder, you can try this:
import os
from os import path
import shutil
sourceDir = os.getcwd()
fixedLength = len(sourceDir)
destDir = '<absolute-path>'
filteredFiles = []
for root, dirs, files in os.walk(sourceDir):
# Filter out only '.txt' files in all the inbox directories.
if root.endswith('inbox'):
# here I am joining the file name to the full path while filtering txt files
files = [path.join(root, f) for f in files if f.endswith('.txt')]
# add the filtered files to the main list
filteredFiles.extend(files)
# making a tuple of file path and file name
filteredFiles = [(f, f[fixedLength+1:].replace('/', '-')) for f in filteredFiles]
for (f, n) in filteredFiles:
print 'copying file...', f
# copying from the path to the dest directory with specific name
shutil.copy(f, path.join(destDir, n))
print 'copied', str(len(filteredFiles)), 'files to', destDir
If you need to copy all files instead of just txt files, then just change the condition f.endswith('.txt') to os.path.isfile(f) while filtering out the files.
I want to copy all my JPG files in one directory to a new directory.
How can I solve this in Python?I just start to learn Python.
Thanks for your reply.
Of course Python offers all the tools you need. To copy files, you can use shutil.copy(). To find all JPEG files in the source directory, you can use glob.iglob().
import glob
import shutil
import os
src_dir = "your/source/dir"
dst_dir = "your/destination/dir"
for jpgfile in glob.iglob(os.path.join(src_dir, "*.jpg")):
shutil.copy(jpgfile, dst_dir)
Note that this will overwrite all files with matching names in the destination directory.
import shutil
import os
for file in os.listdir(path):
if file.endswith(".jpg"):
src_dir = "your/source/dir"
dst_dir = "your/dest/dir"
shutil.move(src_dir,dst_dir)
Just use the following code
import shutil, os
files = ['file1.txt', 'file2.txt', 'file3.txt']
for f in files:
shutil.copy(f, 'dest_folder')
N.B.: You're in the current directory.
If You have a different directory, then add the path in the files list.
i.e:
files = ['/home/bucket/file1.txt', '/etc/bucket/file2.txt', '/var/bucket/file3.txt']
for jpgfile in glob.iglob(os.path.join(src_dir, "*", "*.jpg")):
shutil.copy(jpgfile, dst_dir)
You should write "**" before ".jpg" to search child directories. more "" means more subdirectory to search