Move file to new directory only if it contains specified string - python

I have 1 folder with thousands of files and I need to loop through every single file and see if that file contains a specific string, once it has concluded that it has a specific string, it must then be moved to the correct folder. So far I have:
for filename in glob.iglob('*.txt'):
f = open(filename)
s = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
if s.find('* Test Outcome : FAIL') != -1:
src_file = os.path.join(dirSTART, filename)
dst_file = os.path.join(dirFAIL, filename)
shutil.move(src_file, dst_file + filename)
At the moment, it only moves the first file but I know for a fact there's more.
Thanks

You can use the os module alone to do this.
import os
import shutil
source_dir = "this/is/source/folder"
dest_dir = "this/is/destination/folder"
for top, dirs, files in os.walk(source_dir):
for filename in files:
if not filename.endswith('.txt'):
continue
file_path = os.path.join(top, filename)
with open(file_path, 'r') as f:
if '* Test Outcome : FAIL' in f.read():
shutil.move(file_path, os.path.join(dest_dir, filename))
CAUTION: Since I don't know much about your code, I am assuming all of the files are txt, that they are small and the string you are matching will always be the same.

from re import compile
pattern = compile("\* Test Outcome : FAIL")
for filename in glob.iglob('*.txt'):
fl = open(filename, 'r')
for i in fl.readlines():
if pattern.search(i):
fl.close()
src_file = os.path.join(dirSTART, filename)
dst_file = os.path.join(dirFAIL, filename)
shutil.move(src_file, dst_file + filename)
break #To stop checking other lines

Use a contextmanager and with to open your files so they will be closed each time:
from mmap import mmap, ACCESS_READ
import contextlib
from os import path
from shutil import move
for filename in glob.iglob('*.txt'):
with open(filename) as f:
with contextlib.closing(mmap(f.fileno(), 0, access=ACCESS_READ)) as s:
if s.find('* Test Outcome : FAIL') != -1:
src_file = path.join(dirSTART, filename)
dst_file = path.join(dirFAIL, filename)
move(src_file, dst_file)

Try to do f.close() after s = mmap.mmap(...)
Are you on Linux? If so, might be quicker to this in a shell command with grep and mv.

Related

Python - copy specific file from subfolder to destination, get filename from text file

I want to get my script to read a list of names from a list(txt), then search for those in a selected folder with subfolders, then copy and paste those files to another selected folder. My script running without error but no result.
My script:
import os
import os.path
import shutil
textFile = ("D:\\Test\\list.txt")
sourceFolder = ("D:\\Test")
destinationFolder = ("D:\\")
filesToFind = []
with open(textFile, "r") as tx:
for row in tx:
filesToFind.append(row.strip())
for root, dirs, filename in os.walk(sourceFolder):
if filename in filesToFind:
f = os.path.join(root, filename)
shutil.copy(f, destinationFolder)
Haven’t test it but I think this will work - change this:
for root, dirs, filename in os.walk(sourceFolder):
if filename in filesToFind:
f = os.path.join(root, filename)
shutil.copy(f, destinationFolder)
To this:
for root, dirs, filenames in os.walk(sourceFolder):
for filename in filenames:
if filename in filesToFind:
f = os.path.join(root, filename)
shutil.copy(f, destinationFolder)
# Same code using glob #
## More efficient and also tested one ##
## One more feature added- checks file name given present or not ##
import os
import os.path
import shutil
import glob
textFile = ("D:\\Test\\list.txt")
sourceFolder = ("D:\Test")
destinationFolder = ("D:\\")
f = open(textFile, "r").readlines()
for i in f:
ListFile= glob.glob(os.path.join(sourceFolder,"**",i.strip()),recursive=True)
if len(ListFile):
print(ListFile[0],destinationFolder,os.path.basename(ListFile[0]))
destinationfile=os.path.join(destinationFolder,os.path.basename(ListFile[0]))
shutil.copyfile(ListFile[0],destinationfile)
else:
print(i,"-File not found")

How to conatenate the contents of files in directory to a single file?

I'm trying to concatenate the contents of files available in directory to a single master file. Where in the each content should be spaced along with the file name.
import os
import time
import glob
# List avaialbe directory
for dir in os.listdir('.'):
if os.path.isdir(dir):
print("The available directories are \t" + dir)
# ChangeDirectory
os.chdir(dir)
for file in glob.glob("*.sql"):
# print("The files are: " + file)
readFiles = open(file, 'r').read()
print("the files are", file)
masterFile = open('Master.sql', 'w')
for fileContents in readFiles:
masterFile.write(str(fileContents))
masterFile.close()
print("Closing in 1sec")
time.sleep(1)
I expect the master file should contain the contents of each file present in directory and in master file the contents of each file should be spaced with the file names
You can open master file before loop and close after loop.
Open readFile without `read()
readFile = open(filename, 'r')
but use read() in
masterFile.write(readFile.read())
I'm not sure if it will need '\n' at the end
masterFile.write(readFile.read() + '\n')
To add file name use
masterFile.write(filename + '\n')
dir and file are reserved words so I use dirname and filename
import os
import time
import glob
masterFile = open('Master.sql', 'w')
for dirname in os.listdir('.'):
if os.path.isdir(dirname):
print("directory:", dirname)
os.chdir(dirname)
for filename in glob.glob("*.sql"):
print("filename:", filename)
masterFile.write(filename + '\n')
readFile = open(filename, 'r')
masterFile.write(readFile.read())
#masterFile.write(readFile.read() + '\n')
readFile.close()
masterFile.close()
print("Closing in 1sec")
time.sleep(1)
The same using with so it doesn't need close()
import os
import time
import glob
with open('Master.sql', 'w') as masterFile:
for dirname in os.listdir('.'):
if os.path.isdir(dirname):
print("directory:", dirname)
os.chdir(dirname)
for filename in glob.glob("*.sql"):
print("filename:", filename)
masterFile.write(filename + '\n')
with open(filename, 'r') as readFile:
masterFile.write(readFiles.read())
#masterFile.write(readFiles.read() + '\n')
print("Closing in 1sec")
time.sleep(1)
EDIT: for two started folders "A" and "B". But as before it check sql in subfolders of started folder, but not directly in started folder.
import os
import time
import glob
home_dir = os.getcwd()
with open('Master.sql', 'w') as masterFile:
for start_dir in ['A', 'B']:
# go to directory
os.chdir(start_dir)
for dirname in os.listdir('.'):
if os.path.isdir(dirname):
print("directory:", dirname)
os.chdir(dirname)
for filename in glob.glob("*.sql"):
print("filename:", filename)
masterFile.write('--' + filename + '\n\n')
with open(filename, 'r') as readFile:
masterFile.write(readFiles.read())
#masterFile.write(readFiles.read() + '\n')
# go back
os.chdir(home_dir)
print("Closing in 1sec")
time.sleep(1)

python How do I import multiple .txt files in a folder to add characters to each .txt file?

There are text files of various names in the folder 'a'. I want to read all of these text files and add the letter 'b' to each text file. What should I do?
cwd = os.getcwd()
input_dir = os.path.join(cwd, "my .txt files dir")
sorts = sorted(glob(input_dir), key = lambda x:(len(x) , x))
for f in sorts :
f = open(input_dir, 'a')
data = "add text"
f.write(data)
f.close()
Append data to file:
- first: get all file in folder a.
- second: find extension with .txt.
- third: open it and do something('append', or 'rewrite').
Demo:
import os
# your .txt files dir
path = 'a'
# append data what you want
appendData = 'b'
fileNames = list(os.walk(path))[0][2]
fileNames.sort(key=len)
fileNums = len(fileNames)
# your dst file extension
fileExt = '.txt'
# # Extract extension from filename
# fileExt = os.path.splitext(fileNames[0])[1]
for fileName in fileNames:
if fileName.endswith(fileExt):
fileFullPath = os.path.join(path, fileName)
with open(fileFullPath, 'a') as f:
f.write(appendData)
Like the others said, this is an easy question that could easily be find on google. Anyway here's how to do it:
from os import listdir
from os.path import isfile, isdir, join
files = [file for file in listdir("files") if isfile(join("files", file))]
directories = [directory for directory in listdir("files") if isdir(join("files", directory))]
print(files)
for file_name in files:
try:
file = open("files/" + file_name, "a")
file.write("b")
file.close()
except IOError as err:
print("Could not open file because : ", err)
Replace "file" with the directory where your files are or the path to that directory like "directory0/directory1/directory_with_files"
Avoid to open files with
f = open(input_dir, 'a')
f.close()
Instead
with open(input_dir, 'a') as inputFile:
Do something
Also what you want is
import os
import glob # We will use this module to open only .txt files
path = 'your/path'
for filename in glob.glob(os.path.join(path, '*.txt'))
with open(filename, 'a') as inputFile:
inputFile.write('b')

I have a ".txt "file which consists of various filenames and I want to search each filename in a folder where these files are actually kept

Suppose I have a text file aiq_hits.txt.
Each line in this file corresponds a filename
ant1.aiq
ant2.aiq
ant3.aiq
ant4.aiq
I want to match each line of my textfile (ant1.aiq,ant2.aiq and so on) with filenames which are present at some specific place(R:\Sample) and extract matching files into some other place (R:\sample\wsa).
I have an idea that I need to use functions like os.walk() and fnmatch.fnmatch(), shutil.copy() but I am not able to implement them
My code:
import os
import shutil
import fnmatch
with open("aiq_hits.txt","r") as in_file:
for line in in_file:
I am stuck here
import os
import shutil
sourceDir = "R:\\Sample"
targetDir = "R:\\Sample\\wsa"
existingFiles = set(f for f in os.listdir(sourceDir) if os.path.isfile(os.path.join(sourceDir, f)))
infilepath = "aiq_hits.txt"
with open(infilepath) as infile:
for line in infile:
fname = line.strip()
if fname not in existingFiles: continue
shutil.move(os.path.join(sourceDir, fname), os.path.join(targetDir, fname))
I hope this will suffice:
import os
def match_files(url,file_read, dest):
f = open(file_read, 'rb')
file_list = os.listdir(url)
print(file_list)
saved_path = os.getcwd()
print("Current working directory is " + saved_path)
os.chdir(url)
match = []
for file_name in f:
file_name = file_name.strip()
if file_name in file_list:
match.append(file_name)
os.rename(os.path.join(url, file_name), os.path.join(dest, file_name))
os.chdir(saved_path)
print match
here, url is source directory or folder from which u want to match files, file_read is the name of file (with path) in which list of file names is given, dest is the destination folder.
this code moves the matching files from url to dest, i.e. these files won't remin in url after running the code.
Alternatively you could use the glob module which allows you to enter in a expression for the file name\extension which will then return a list that you can loop over.
I'd use this module if the source directory can have files with the same extension that you want to exclude from being looped over
Also I'm assuming that the file name list is not large and so storing it in a list wont be an issue
eg (I haven't tested the below )
from glob import glob
import os
import shutil
src = 'R:\\Sample'
dst = "R:\\Sample\\wsa"
in_file_list = "aiq_hits.txt"
list_Of_files = glob(os.path.join(src, 'ant*.aiq'))
data = []
with open(in_file_list) as reader:
data += reader.readlines()
for row in list_Of_files:
file_path, file_name = os.path.split(row)
if file_name in data:
shutil.copy2(row, os.path.join(dst, file_name))
# or if you want to move the file
# shutil.move(row, os.path.join(dst, file_name))

Python: Read multiple files and move them to a directory according to their content

I am quite new to python, but I would like to use it for the following tasks:
read all files in a directory
look for a specific character in all lines of the files
if this character is present only once in the file copy the file in a specific directory.
I tried the following code:
#! /usr/bin/python
import glob
import shutil
path = '/xxxx/Dir/*.txt'
files=glob.glob(path)
for file in files:
f=open(file)
f.read()
total = 0
for line in f:
if "*TPR_4*" in line:
total_line = total + 1
if total_line == 1:
shutil.copy(f, 'xxxx/Test/')
f.close()
However, it is not working.
Any suggestion?
shutil.copy() takes file names as arguments not open files. You should change your call:
shutil.copy(file, 'xxxx/Test/')
Also: file is a poor name choice. It's a built-in function's name.
The logic is not quite correct, also you are mixing up total and total_line and shutil.copy takes the name, not the object as an argument. And note that the if .. in line does not use globbing syntax, i.e. to search for TPR_4, use 'TPR_4', not '*TPR_4*'. Try the following:
#! /usr/bin/python
import glob
import shutil
path = '/xxxx/Dir/*.txt'
files=glob.glob(path)
for file in files:
f=open(file)
total = 0
for line in f:
if "TPR_4" in line:
total += 1
if total > 1:
break # no need to go through the file any further
f.close()
if total == 1:
shutil.copy(file, 'xxxx/Test/')
I wrote some code for your question, maybe it's good for you.
import os, shutil
dir_path = '/Users/Bob/Projects/Demo'
some_char = 'abc'
dest_dir = "/Users/Bob/tmp"
for root, dirs, files in os.walk(dir_path):
for _file in files:
file_path = os.path.join(root, _file)
copy = False
with open(file_path, 'r') as f:
while True:
line = f.readline()
if not line:
break
if str(line).find(some_char) > -1:
copy = True
break
if copy:
shutil.copy(file_path, dest_dir)
print file_path, ' copy...'

Categories

Resources