I have two folders with images. Let the two folder names A and B. A contains 100 files and B has only 80 files. Both the files have the same name. I want to save only the 80 files from A which has the same correspondence to B in folder C.
Here is a part of my code. However, it is throwing error :
Required argument 'img' (pos 2) not found.
path1= '/home/vplab/Kitty/Saliency Dataset/PiCANet-Implementation/TrainSet/images'
path_mask= '/home/vplab/Kitty/Saliency Dataset/PiCANet-Implementation/TrainSet/masks'
save_path = '/home/vplab/Kitty/Saliency Dataset/PiCANet-Implementation/TrainSet/exp'
for file in os.listdir(path1):
for file1 in os.listdir(path_mask):
img_name = file[:-4]
mask_name =file1[:-4]
if img_name == mask_name:
cv2.imwrite(os.path.join(save_path,img_name))
Your issue here is that you are not passing a file object to cv2.imwrite(os.path.join(save_path,img_name)) when trying to perform the copy; that's what the error is telling you.
However, your current approach includes a nested for loop which will give poor performance. If you only want to know the files that the directories have in common, you can create a set of the file names in each directory and find the intersection. Then you just need to iterate through the common files and copy them over (as said in the comments, there's no need for cv2 here - they may be images but they're just regular files that can be copied).
import os
from shutil import copyfile
dir_1 = 'A'
dir_2 = 'B'
output_dir = 'C'
files_1 = os.listdir(dir_1)
files_2 = os.listdir(dir_2)
# Find the common files between both
common_files = set(files_1).intersection(files_2)
# Copy the common files over.
for file in common_files:
copyfile(os.path.join(dir_1, file),
os.path.join(output_dir, file))
If the reason that you are stripping the last characters from the files in os.listdir is because the files have the same name but different extensions, you only need to make two small modifications (where here I'm assuming the extension is .png that needs to be added back later):
files_1 = [item[:-4] for item in os.listdir(dir_1)]
files_2 = [item[:-4] for item in os.listdir(dir_2)]
And:
for file in common_files:
file = file + '.png' # Add the extension back on to the file name
copyfile(os.path.join(dir_1, file),
os.path.join(output_dir, file))
The any() method returns True if any element of an iterable is True. If not, any() returns False. shutil.copy - Copies the file src to the file or directory dst.
import os
import shutil
def read_file(folderName,folderPath):
''' Return list of files name '''
path = folderPath+folderName
return [file for file in os.listdir(path)]
def save_file(soureFolderName,destFolderName,folderPath,fileName):
''' Save file on destination folder'''
try:
source_path = folderPath+soureFolderName+"/"+fileName
dest_path = folderPath+destFolderName+"/"+fileName
shutil.copy(source_path, dest_path)
except Exception as e:
print(e)
base_path = '/home/vplab/Kitty/Saliency Dataset/PiCANet-Implementation/TrainSet/'
folder_images_files = read_file('images',base_path)
folder_masks_file = read_file('masks',base_path)
for file_1 in folder_images_files:
#Check folder A file is exists in folder B
if any(file_1 == file_2 for file_2 in folder_masks_file):
save_file("images","exp",base_path,file_1)
Related
Hi everyone I´m trying now to move some files from one folder to another. The files that i have are
results_1_1
results_2_1
results_3_1
results_1_2
results_2_2
results_3_2
What i´d like to get is to move files
results_1_1
results_2_1
results_3_1 to one folder let´s call it A
other
results_1_2
results_2_2
results_3_2 to another let´s call it B
I don´t want to do it manually because, in reality, I have much more files
I have created by python a new folder that I want to have
and so far about moving the files to another directory
import shutil
source_folder = r"C:/Users/...."
destination_folder= r"C:/Users/...."
files_to_move = ['results_1_3.dat']
for file in files_to_move:
source = source_folder + file
destination = destination_folder + file
shutil.move(source,destination)
print("Moved!")
But with this program I can only move one file at a time I tried writing results_.+3.dat', results*_3.dat' but I´m seeing an error all the time
You can use os.listdir to find all the files in your directory.
This code finds all the files which names end with '1'.
import os
files_to_move = [f for f in os.listdir() if f.split('.')[0][-1] == '1']
You can also add an extension check if necessary:
files_to_move = [f for f in os.listdir() if f.split('.')[0][-1] == '1' and f.split('.')[1] == 'dat']
You can list all files in your directory using os.listdir(source_folder)
If you have mixed files in your directory, you can select your results files with something like this
files_to_move = [x for x in os.listdir(source_folder) if all(j in x for j in ['results', '.dat'])]
I would then create a dictionary containing the destination folders associated with the numbers in your results file.
destination_A = r'/path/to/destinationA'
destination_B = r'/path/to/destinationB'
moving_dict = {
'1': destination_A,
'2': destination_B
}
You can then move your files based on the filename
for file in files_to_move:
destination_folder = moving_dict[file[:-4].split('_')[-1]]
source = source_folder + file
destination = destination_folder + file
shutil.move(source,destination)
I have to complete this function according to these instructions, I have tried looping thru with for loop and ever the os.path approach but still cant figure it out? how can I Improve upon this?
def copy_files():
Open each .txt file in the datafiles folder.
datafiles contain 10 .txt files with numbers separated by ','. Each file in datafiles is named file00, file01, file0(+=1)...
Read in the text and then write it back out to an identically named file in the mydatafiles sub-folder within the myfiles folder.
You have to achieve this by reading in the text from each file as a string and then writing it back out to the new file.
This function requires no error handling and has no return value.
When done, the mydatafiles folder will contain a copy of each file within the datafiles folder.
from shutil import copyfile
def copy_files():
src_files = os.listdir('datafiles')
for file_name in src_files:
full_file_name = os.path.join('datafiles', file_name)
if os.path.isfile(full_file_name):
copyfile(full_file_name, 'mydatafiles')
Alternative approach:
from shutil import copyfile
def copy_files():
completeName = os.path.join('myfiles', "mydatafiles")
new_file = " "
for file in 'datafiles':
new_file += file
incompleteName = os.path.join('datafiles', new_file)
with open(incompleteName,'r') as firstfile, open('completeName','a') as secondfile:
for line in firstfile:
# write content to second file
secondfile.write(line)
I'd appreciate any help
for shutil.copyfile(src, dst) destination must complete filename not directory, use copy() to use directory as destination
def copy_files():
src_files = os.listdir('datafiles')
for file_name in src_files:
full_file_name = os.path.join('datafiles', file_name)
if os.path.isfile(full_file_name):
targetFile = os.path.join('mydatafiles', file_name)
copyfile(full_file_name, targetFile)
# or
# copy(full_file_name, 'mydatafiles')
The purpose of this code is:
Read a csv file which contains a column for a list of file names
here is the csv file:
https://drive.google.com/open?id=0B5bJvxM9TZkhVGI5dkdLVzAyNTA
Then check a specific folder to check if the files exist or not
If its found a file is not in the list delete it
here is the code:
import pandas as pd
import os.path
data = pd.read_csv('data.csv')
names = data['title']
path = "C:\\Users\\Sayed\\Desktop\\Economic Data"
for file in os.listdir(path):
os.path.exists(file)
print(file)
file = os.path.join(path, file)
fileName = os.path.splitext(file)
if fileName not in names:
print('error')
os.remove(file)
I modified the first code, and this is the new code and I got no error but the simply delete all the files in the directory
os.chdir does not return anything, so assigning the result to path means that path has None, which causes the error.
Since you're using pandas, here's a little trick to speed this up using pd.Series.isin.
root = "C:\Users\Sayed\Desktop\Economic Data"
files = os.listdir(root)
for f in data.loc[~data['title'].isin(files), 'title'].tolist():
try:
os.remove(os.path.join(root, f))
except OSError:
pass
Added a try-except check in accordance with EAFP (since I'm not doing an os.path.exists check here). Alternatively, you could add a filter based on existence using pd.Series.apply:
m = ~data['title'].isin(files) & data['title'].apply(os.path.exists)
for f in data.loc[m, 'title'].tolist():
os.remove(os.path.join(root, f))
Your path is the return value of the os.chdir() call. Which is obviously None.
You want to set path to the string representing the path ... leave the chdir out.
I have been working this challenge for about a day or so. I've looked at multiple questions and answers asked on SO and tried to 'MacGyver' the code used for my purpose, but still having issues.
I have a directory (lets call it "src\") with hundreds of files (.txt and .xml). Each .txt file has an associated .xml file (let's call it a pair). Example:
src\text-001.txt
src\text-001.xml
src\text-002.txt
src\text-002.xml
src\text-003.txt
src\text-003.xml
Here's an example of how I would like it to turn out so each pair of files are placed into a single unique folder:
src\text-001\text-001.txt
src\text-001\text-001.xml
src\text-002\text-002.txt
src\text-002\text-002.xml
src\text-003\text-003.txt
src\text-003\text-003.xml
What I'd like to do is create an associated folder for each pair and then move each pair of files into its respective folder using Python. I've already tried working from code I found (thanks to a post from Nov '12 by Sethdd, but am having trouble figuring out how to use the move function to grab pairs of files. Here's where I'm at:
import os
import shutil
srcpath = "PATH_TO_SOURCE"
srcfiles = os.listdir(srcpath)
destpath = "PATH_TO_DEST"
# grabs the name of the file before extension and uses as the dest folder name
destdirs = list(set([filename[0:9] for filename in srcfiles]))
def create(dirname, destpath):
full_path = os.path.join(destpath, dirname)
os.mkdir(full_path)
return full_path
def move(filename, dirpath):
shutil.move(os.path.join(srcpath, filename)
,dirpath)
# create destination directories and store their names along with full paths
targets = [
(folder, create(folder, destpath)) for folder in destdirs
]
for dirname, full_path in targets:
for filename in srcfile:
if dirname == filename[0:9]:
move(filename, full_path)
I feel like it should be easy, but Python isn't something I work with everyday and it's been a while since my scripting days... Any help would be greatly appreciated!
Thanks,
WK2EcoD
Use the glob module to interate all of the 'txt' files. From that you can parse and create the folders and copy the files.
The process should be as simple as it appears to you as a human.
for file_name in os.listdir(srcpath):
dir = file_name[:9]
# if dir doesn't exist, create it
# move file_name to dir
You're doing a lot of intermediate work that seems to be confusing you.
Also, insert some simple print statements to track data flow and execution flow. It appears that you have no tracing output so far.
You can do it with os module. For every file in directory check if associated folder exists, create if needed and then move the file. See the code below:
import os
SRC = 'path-to-src'
for fname in os.listdir(SRC):
filename, file_extension = os.path.splitext(fname)
if file_extension not in ['xml', 'txt']:
continue
folder_path = os.path.join(SRC, filename)
if not os.path.exists(folder_path):
os.mkdir(folderpath)
os.rename(
os.path.join(SRC, fname),
os.path.join(folder_path, fname)
)
My approach would be:
Find the pairs that I want to move (do nothing with files without a pair)
Create a directory for every pair
Move the pair to the directory
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import os, shutil
import re
def getPairs(files):
pairs = []
file_re = re.compile(r'^(.*)\.(.*)$')
for f in files:
match = file_re.match(f)
if match:
(name, ext) = match.groups()
if ext == 'txt' and name + '.xml' in files:
pairs.append(name)
return pairs
def movePairsToDir(pairs):
for name in pairs:
os.mkdir(name)
shutil.move(name+'.txt', name)
shutil.move(name+'.xml', name)
files = os.listdir()
pairs = getPairs(files)
movePairsToDir(pairs)
NOTE: This script works when called inside the directory with the pairs.
im trying to copy a .txt file from one dest to another. This code is running but the file isnt copying. What am i doing wrong?
import shutil
import os
src = "/c:/users/mick/temp"
src2 = "c:/users/mick"
dst = "/c:/users/mick/newfolder1/"
for files in src and src2:
if files.endswith(".txt"):
shutil.copy(files, dst)
Your for loop isn't actually searching through the files of each of your sources. In addition your for loop isn't looping through each of the sources but rather the letters in src and src2 that are present in both. This adjustment should handle what you need.
import os
src = ["c:/users/mick/temp", "c:/users/mick"]
dst = "c:/users/mick/newfolder1/"
for source in src:
for src_file in os.listdir(source):
if src_file.endswith(".txt"):
old_path = os.path.join(source, src_file)
new_path = os.path.join(dst, src_file)
os.rename(old_path, new_path)
You shouldn't need shutil for this situation as it is simply a more powerful os.rename that attempts to handle different scenarios a little better (to my knowledge). However if "newfolder1" isn't already existant than you will want to replace os.rename() with os.renames() as this attempts to create the directories inbetween.
shutils is useful for copying, but to move a file use
os.rename(oldpath, newpath)
I know the question is little older. But Here are the simple way to achieve your task. You may change the file extension as you wish. For copying you may use copy() & for moving yo may change it to move(). Hope this helps.
#To import the modules
import os
import shutil
#File path list atleast source & destination folders must be present not everything.
#*******************************WARNING**********************************************
#Make sure these folders names are already created while using the 'move() / copy()'*
#************************************************************************************
filePath1 = 'C:\\Users\\manimani\\Downloads' #Downloads folder
filePath2 = 'F:\\Projects\\Python\\Examples1' #Downloads folder
filePath3 = 'C:\\Users\\manimani\\python' #Python program files folder
filePath4 = 'F:\\Backup' #Backup folder
filePath5 = 'F:\\PDF_Downloads' #PDF files folder
filePath6 = 'C:\\Users\\manimani\\Videos' #Videos folder
filePath7 = 'F:\\WordFile_Downloads' #WordFiles folder
filePath8 = 'F:\\ExeFiles_Downloads' #ExeFiles folder
filePath9 = 'F:\\Image_Downloads' #JPEG_Files folder
#To change the directory from where the files to look // ***Source Directory***
os.chdir(filePath8)
#To get the list of files in the specific source directory
myFiles = os.listdir()
#To move all the '.docx' files to a different location // ***Destination Directory***
for filename in myFiles:
if filename.endswith('.docx'):
print('Moving the file : ' + filename)
shutil.move(filename, filePath4) #Destination directory name
print('All the files are moved as directed. Thanks')
import os, shutil
src1 = "c:/users/mick/temp/"
src2 = "c:/users/mick/"
dist = "c:/users/mick/newfolder"
if not os.path.isdir(dist) : os.mkdir(dist)
for src in [src1, src2] :
for f in os.listdir(src) :
if f.endswith(".txt") :
#print(src) # For testing purposes
shutil.copy(src, dist)
os.remove(src)
I think the error was that you were trying to copy a directory as a file, but you forgot to go through the files in the directory. You were just doing shutil.copy("c:/users/mick/temp/", c:/users/mick/newfolder/").