How can I copy files from a folder into multiple folders - python

I have 130 files in a folder source and I want to copy each files in a single folder 001, 002, 003 ... 130 (all these 130 folders are located in destination folder).
So that every folder contain just one file.
I came up with this but probably it's a bit messy and redundant... and mostly it doesn't work.
import shutil
import os
source = '/Users/JohnCN/photo_database/mugshot_frontal/'
files = os.listdir(source)
for i in files:
for fold in range(1,131):
if fold<10:
destination = "/Users/JohnCN/photo_DBsorted/00%s" %fold
shutil.move(source+i, destination)
elif fold in range(10,100):
destination = "/Users/JohnCN/photo_DBsorted/0%s" %fold
shutil.move(source+i, destination)
else:
destination = "/Users/JohnCN/photo_DBsorted/%s" %fold
shutil.move(source+i, destination)

I would do it the following way:
import shutil
import os
source = '/Users/JohnCN/photo_database/mugshot_frontal/'
files = os.listdir(source)
for idx, f in enumerate(files):
destination = '/Users/JohnCN/photo_DBsorted/{d:03d}'.format(d=(idx + 1))
shutil.move(source + f, destination)
So, what does it do?
for idx, f in enumerate(files): counts the files while looping, so you know the index of the file. To get the destination, the idx is used as directory name. I assume you know the method format, {d:03d} simply says, that the value d is assigned to should be 3 characters long, the value is an integer and it's padded with zeros (e.g. 003). Of course, this code assumes that you do not have 1000+ files, in that case, just increase the number of zeroes. You could for example calculate the log10-value of the number of files to get the number of zeros you have to add.

First of all, I would rather use shutil.copy if I wanted to copy the files, but not to move. Though, the main idea does not depend on it. Also you don't need no if statements here as well as the inner cycle:
files = os.listdir(source)
for i in range(len(files)):
file = os.path.join(source, files[i])
shutil.copy(file, os.path.join(source, '%03d'%i, files[i])

Related

os.walk folder exclusion based on .txt file

I would like to have a Folders_To_Skip.txt file with a list of directories separated by new lines
ex:
A:\\stuff\a\b\
A:\\junk\a\b\
I have files which are breaking my .csv record compiling that this is used for and I want to exclude directories which I have no use for reading anyway.
In the locate function I have what I tried to implement from Excluding directories in os.walk but I can't seem to get it to work with directories in a list let alone while reading from a text file list as when I print files accessed it still includes files in the directories I attempted to exclude.
Could you also explain whether the solution would be specific excluded directories (not the end of the world) or if it can be operated to exclude subdirectories (would be more convenient).
Right now the code preceding locate allows for easy lookup of controlling text files and then loading those items in as lists for the rest of the script to run, with the assumption that all control files are in the same location but that location can change based on who is running the script and from where.
Also for testing purposes Drive_Locations.txt is setup as:
A
B
Here is the current script:
import os
from tkinter import filedialog
import fnmatch
input('Press Enter to select any file in writing directory or associated control files...')
fname = filedialog.askopenfilename()
fpath = os.path.split(fname)
# Set location for Drive Locations to scan
Disk_Locations = os.path.join(fpath[0], r'Drive_Locations.txt')
# Set location for Folders to ignore such as program files
Ignore = os.path.join(fpath[0], r'Folders_To_Skip.txt')
# Opens list of Drive Locations to be sampled
with open(Disk_Locations, 'r') as Drives:
Drive = Drives.readlines()
Drive = [x.replace('\n', '') for x in Drive]
# Iterable list for directories to be excluded
with open(Ignore, 'r') as SkipF1:
Skip_Fld = SkipF1.readlines()
Skip_Fld = [x.replace('\n', '') for x in Skip_Fld]
# Locates file in entire file tree from previously established parent directory.
def locate(pattern, root=os.curdir):
for path, dirs, files in os.walk(os.path.abspath(root), topdown=True):
dirs[:] = [d for d in dirs if d not in Skip_Fld]
for filename in fnmatch.filter(files, pattern):
yield os.path.join(path, filename)
for disk in Drive:
# Formats Drive Location for acceptance
disk = str.upper(disk)
if str.find(disk, ':') < 0:
disk = disk + ':'
# Changes the current disk drive
if os.path.exists(disk):
os.chdir(disk)
# If disk incorrect skip to next disk
else:
continue
for exist_csv in locate('*.csv'):
# Skip compiled record output files in search
print(exist_csv)
The central bug here is that os.walk() returns a list of relative directory names. So for example when you are in the directory A:\stuff\a, the directory you want to skip is simply listed as b, not as A:\stuff\a\b; and so of course your skip logic doesn't find anything to remove from the list of subdirectories in the current directory.
Here's a refactoring which examines the current directory directly instead.
for path, dirs, files in os.walk(os.path.abspath(root), topdown=True):
if path not in Skip_Fld:
for filename in fnmatch.filter(files, pattern):
yield os.path.join(path, filename)
The abspath call is important to keep; good on you for including that in your attempt.
Your list of directories to skip should have single backslashes, or perhaps forward slashes, and probably no final directory separator (I fortunately have no way to check how these are reported by os.walk() on Windows).

How to find and copy almost identical filenames from one folder to another using python?

I have a folder with a large number of files (mask_folder). The filenames in this folder are built as follows:
asdgaw-1454_mask.tif
lkafmns-8972_mask.tif
sdnfksdfk-1880_mask.tif
etc.
In another folder (test_folder), I have a smaller number of files with filenames written almost the same, but without the addition of _mask. Like:
asdgaw-1454.tif
lkafmns-8972.tif
etc.
What I need is a code to find the files in mask_folder that have an identical start of the filenames as compared to the files in test_folder and then these files should be copied from the mask_folder to the test_folder.
In that way the test_folder contains paired files as follows:
asdgaw-1454_mask.tif
asdgaw-1454.tif
lkafmns-8972_mask.tif
lkafmns-8972.tif
etc.
This is what I tried, it runs without any errors but nothing happens:
import shutil
import os
mask_folder = "//Mask/"
test_folder = "//Test/"
n = 8
list_of_files_mask = []
list_of_files_test = []
for file in os.listdir(mask_folder):
if not file.startswith('.'):
list_of_files_mask.append(file)
start_mask = file[0:n]
print(start_mask)
for file in os.listdir(test_folder):
if not file.startswith('.'):
list_of_files_test.append(file)
start_test = file[0:n]
print(start_test)
for file in start_test:
if start_mask == start_test:
shutil.copy2(file, test_folder)
The past period I searched for but not found a solution for above mentioned problem. So, any help is really appreciated.
First, you want to get only the files, not the folders as well, so you should probably use os.walk() instead of listdir() to make the solution more robust. Read more about it in this question.
Then, I suggest loading the filenames of the test folder into memory (since they are the smaller part) and then NOT load all the other files into memory as well but instead copy them right away.
import os
import shutil
test_dir_path = ''
mask_dir_path = ''
# load file names from test folder into a list
test_file_list = []
for _, _, file_names in os.walk(test_dir_path):
# 'file_names' is a list of strings
test_file_list.extend(file_names)
# exit after this directory, do not check child directories
break
# check mask folder for matches
for _, _, file_names in os.walk(mask_dir_path):
for name_1 in file_names:
# we just remove a part of the filename to get exact matches
name_2 = name_1.replace('_mask', '')
# we check if 'name_2' is in the file name list of the test folder
if name_2 in test_file_list:
print('we copy {} because {} was found'.format(name_1, name_2))
shutil.copy2(
os.path.join(mask_dir_path, name_1),
test_dir_path)
# exit after this directory, do not check child directories
break
Does this solve your problem?

Renaming filenames in python without changing the actual number order?

I have files like:
00001.jpg
00002.jpg
.
.
.
01907.jpg
I want to add some files to this directory which are named the same. But their names should continue like
01908.jpg
01909.jpg
.
.
12906.jpg
I couldn't manage to do that. How can i make this happen?
Thanks a lot:)
I tried
import os
files=[]
files = sorted(os.listdir('directory'))
b=len(files)
for i in range(0,b):
a=files[i]
os.rename(a,(a+1))
print (files)
you have a source dir (which contains the badly/identical named files) and a target dir (which contains files that should not be overwritten).
I would:
list the target dir & sort like you did (the rest of your attempt is clearly off...)
get the last item and parse as integer (without extension): add 1 and that gives the next free index.
loop in the source dir
generate a new name for the current file using the new computed index
use shutil.move or shutil.copy to move/copy the new files with the new name
like this:
import os,shutil
s = "source_directory"
d = "target_directory"
files = sorted(os.listdir(d))
highest_index = int(os.path.splitext(files[-1])[0])+1
for i,f in enumerate(sorted(os.listdir(s)),highest_index):
new_name = "{:05}.png".format(i)
shutil.copy(os.path.join(s,f),os.path.join(d,new_name))
You can do this:
import os
directory1 = 'path to the directory you want to move the files to'
directory2 = 'path to the directory you want to move the files to'
for file in ordered(os.listdir(directory2)):
counter = len(os.listdir(directory1))
file_number = int(file.split('.')[0]) #Get the file number
os.rename(os.path.join(directory2, file), os.path.join(directory1 + str(file_number + counter)))
What I have done:
Looped over the files that I wanted to rename and move.
Found the number of files, which I assumed that it is going to be the same as the name of the last file in this directory, in the main directory which the files are going to be moved to and made sure it will keep updating itself so that no overwrites happen.
Then I got the number of the current file in the loop.
Finally, I used os.rename to rename and move the file from the 1st directory to the 2nd.

Renaming files with python to 1.jpg, 2.jpg, etc

First I would like to say I want to do this in python 2.7!
Hi, I have a folder full of images named 1.jpg, 2.jpg, 3.jpg, etc. All the way up to 600.jpg.
I would like to rename them 600 higher, so 601.jpg, 602.jpg, 603.jpg, etc. All the way up to 1200.jpg.
I am honestly not quite sure where to start, so any help would be useful. It doesn't seam like it should be hard but I was not able to name them in ascending order. The best I got was 601.jpg, 601.jpg, and it was the same for every file.
This is what I have currently, it's been altered a few times, and now all I get is an error.
import os
path = '/Users/antse/OneDrive/Documents/Instagram/set_2'
files = os.listdir(path)
i = 601
for file in files:
os.rename(os.path.join(path, file), os.path.join(path, str(i)+'.jpg'))
i = i+1
One of the problems with your approach is that listdir doesn't come back in order from 1.jpg ..., and it includes any other files or subdirectories. But there is no need to list the directory - you already know the pattern of what you want to change and its a hassle to deal with other files that may be there.
import os
path = '/Users/antse/OneDrive/Documents/Instagram/set_2'
for i in range(1, 601):
old_name = os.path.join(path, '{}.jpg'.format(i))
new_name = os.path.join(path, '{}.jpg'.format(i+600))
try:
os.rename(old_name, new_name)
except OSError as e:
print 'could not rename', old_name, e

copy and rename files in a directory in a specific pattern

I would like to copy a file lying in a directory equal to the number of times the other files lying in that directory and then rename all the new files.
For example, there are 3 files in a directory, filename1.xls, filename2.xls and filename3.xls. I would like to copy Filename1.xls 2 times (as there are 2 files in the directory excluding filename1.xls )and then rename each copied file as filename2.xls and fiilename3.xls. Hope my question is clear. Thanks, AD
hm... just get the amount of files in directory, copy your file N times and save them as
for number in range(amount):
"feliname%r.xls" % number
if I understand what you mean
To replace content of all files that have names that start with "F" and that are adjacent to a file given at the command-line with its copy:
#!/usr/bin/env python
import os
import shutil
import sys
filename = sys.argv[1] # provide file you want to multiply
dirname, basename = os.path.split(filename)
for name in os.listdir(dirname):
path = os.path.join(dirname, name)
#note: os.path.normcase() might be required to compare names
if name.startswith("F") and name != basename and os.path.isfile(path):
shutil.copy2(filename, path) #note: some metadata is not copied
Note: if the copy fails; the destination file might be destroyed. You can copy to a temporary file first in this case before replacing the destination.

Categories