Python: Regex file search with shutil using an excel file - python

I have a program I am writing for an internal employee that takes a CSV file and searches a file server for the files listed in the CSV then copys each file to a folder in the desktop. The issue I am running into with my current code is that the CSV must hold the exact names but instead I need to regex search this and copy the files with file names like the ones in the CSV.
file name in excel looks like: D6957-QR-1452
file name on server looks like: WM_QRLabels_D6957-QR-1452_11.5x11.5_M.pdf
from tkinter import filedialog, messagebox
import openpyxl
import tkinter as tk
from pathlib import Path
import shutil
import os
desktop = Path.home() / "Desktop/Comps"
tk.messagebox.showinfo("Select a directory","Select a directory" )
folder = filedialog.askdirectory()
root = tk.Tk()
root.title("Title")
lbl = tk.Label(
root, text="Open the excel file that includes files to search for")
lbl.pack()
frame = tk.Frame(root)
frame.pack()
scrollbar = tk.Scrollbar(frame)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
listbox = tk.Listbox(frame, yscrollcommand=scrollbar.set)
def load_file():
wb_path = filedialog.askopenfilename(filetypes=[('Excel files', '.xlsx')])
wb = openpyxl.load_workbook(wb_path)
global sheet
sheet = wb.active
listbox.pack()
file_names = [cell.value for row in sheet.rows for cell in row]
for file_name in file_names:
listbox.insert('end', file_name)
return file_names # <--- return your list
def search_folder(folder, file_name):
# Create an empty list to store the found file paths
found_files = []
for root, dirs, files in os.walk(folder):
for file in files:
if file in file_name:
found_files.append(os.path.join(root, file))
shutil.copy2(file, desktop)
return found_files
excelBtn = tk.Button(root, text="Open Excel File",
command=None)
excelBtn.pack()
zipBtn = tk.Button(root, text="Copy to Desktop",
command=search_folder(folder, load_file()))
zipBtn.pack()
root.mainloop()
Program is able to find and copy exact file names but unable to file *like* files.

Change your search_folder method to something like this:
def search_folder(folder, file_name):
# Create an empty list to store the found file paths
found_files = []
for root, dirs, files in os.walk(folder):
for file in files:
for file_pattern in file_name:
if file.find(file_pattern) > -1:
replaced_backslashes = re.sub(r"\\+", "/", os.path.join(root, file), 0, re.MULTILINE)
found_files.append(replaced_backslashes)
shutil.copy2(file, desktop)
return found_files
Basically, for every file we iterate over the file_name array to test all the patterns.
For the test we use find method, that in case it matches, returns the position of the found substring.
That is, if searching for 'foo', all these files would be returned:
zazfoo
foobar
zazfoobar
foo

Related

How to get Python to ask for directory, read each filename in the dir and place that filename(without .csv) in the same file respectively?

I'm very new to Python, I have several hundred folders with many thousands of files each containing times series data. Each file has an anonymized unique filename followed by an underscore and file number for each file (0 thru however many files are in the folder) "18667_0.csv, 18667_1.csv, 18667_3.csv" associated with it. I need to run a for loop that will take this unique filename "18667" and place it in whatever cell(Im using excel to read the csv) I choose for the same csv file. So if I have 300 files in the folder all will have the unique "18667" and I just want that number to be placed in the file. I have part of the code for the dir request but I've not been successful in combining the right read/write statements to implement this task. Here's what I have
import tkinter as tk
import pandas as pd
from tkinter import filedialog
from os import listdir
def find_csv_filenames( path_to_dir, suffix=".csv" ):
filenames = listdir(path_to_dir)
return [ filename for filename in filenames if filename.endswith( suffix ) ]
root = tk.Tk()
root.withdraw()
folder_path = filedialog.askdirectory()
all_csvfiles = find_csv_filenames(folder_path, suffix= ".csv")
for filename in all_csvfiles:
print(filename)
a = filename
with open(a, 'w', newline="") as file:
csvwriter = csv.writer(file) # 2. create a csvwriter object
csvwriter.writerow(a)
Wound up doing this.
import tkinter as tk
from tkinter import filedialog
from os import listdir
# Listing all csv in folder
def find_csv_filenames(path_to_dir, suffix=".csv"):
filenames = listdir(path_to_dir) #returns all filenames
return [filename for filename in filenames if filename.endswith(suffix)]
#returns only csv filenames in a list []
#This is GUI for asking to select folder
root = tk.Tk()
root.withdraw()
folder_path = filedialog.askdirectory() #Returns the folder you selected
all_csvfiles = find_csv_filenames(folder_path, suffix=".csv") #lists filenames
print(folder_path)
for filename in all_csvfiles: #begin loop thru all csv files
print(filename)
# a = filename
InsertedName = filename[:-4] #removes last 4 chars from filename
print(InsertedName)
tempfile = open(folder_path + "/temp.csv", "w") # creates a tempfile for
writing(w) in the same dir
tempfile.write(InsertedName+"\n") #will write filename to temp and instruct
for newline
sourcefile = open(folder_path + "/" + filename, "r") #creates a sourcefile
for reading original
for line in sourcefile: #begins loop for writing original data to tempfile
tempfile.write(line) #writes the data
sourcefile.close() #closes sourcefile
Finalfile = open(folder_path + "/" + filename, "w") #creating finalfile to
overwrite existing file in dir
tempfile.close() #closes tempfile to return pointer to the top of file
tempfile = open(folder_path + "/temp.csv", "r") #opens tempfile to write
tempfile data to finalfile
for line in tempfile: #loops the lines to write
Finalfile.write(line)
tempfile.close()
Finalfile.close()

Python expecting expected str, bytes or os.PathLike object, not StringVar

Okay, so I'm working on a project that monitors two selected folders and automatically moves files created or edited within the last twenty-four hours from Folder_A to Folder_B. It also will check the two folders manually when the user clicks the scan button. So far it will select the two folders, but when I click the scan button I get this error. How would I go about fixing the error? My code is below the error. Please be understanding that I am still really new to python, so there might be quite a few really stupid mistakes in here.
File
"C:\Users\--\AppData\Local\Programs\Python\Python310\Projects\File_transfer.py", line 63, in <module>
scan_btn=Button(text="Scan", command = submitFunction())
File "C:\Users\--\AppData\Local\Programs\Python\Python310\Projects\File_transfer.py", line 34, in submitFunction
for root, dirs,files in os.walk(origin_path):
File "C:\Users\quirk\AppData\Local\Programs\Python\Python310\lib\os.py", line 342, in walk
return _walk(fspath(top), topdown, onerror, followlinks)
TypeError: expected str, bytes or os.PathLike object, not StringVar
My code for the project:
import tkinter
import tkinter as tk
from tkinter import *
from tkinter import filedialog
import os,time
import datetime
import shutil
import datetime as dt
def browse_button():
# Allow user to select a directory and store it in global var
# called origin_path
global origin_path
filename = filedialog.askdirectory()
origin_path.set(filename)
print(filename)
def browse_button2():
# Allow user to select a directory and store it in global var
# called receiving_path
global receiving_path
filename = filedialog.askdirectory()
receiving_path.set(filename)
print(filename)
def submitFunction() :
for root, dirs,files in os.walk(origin_path):
for fname in files:
path = os.path.join(root, fname)
st = os.stat(path)
mtime = dt.datetime.fromtimestamp(st.st_mtime)
shutil.move(path, dest)
print('Submit button is clicked.')
root = Tk()
origin_path = StringVar()
receiving_path = StringVar()
#First Browse Button Label
lbl1 = Label(master=root,textvariable=origin_path)
lbl1.grid(row=0, column=1)
#Second Browse Button Label
lbl1_2 = Label(master=root,textvariable=receiving_path)
lbl1_2.grid(row=1, column=1)
lbl1_3 = Label(master=root)
lbl1_3.grid(row=2, column=1)
button = Button(text="Browse", command=browse_button)
button.grid(row=0, column=3)
button2 = Button(text="Browse", command=browse_button2)
button2.grid(row=1, column=3)
scan_btn=Button(text="Scan", command = lambda:submitFunction())
scan_btn.grid(row=2, column=7)
mainloop()
now = dt.datetime.now()
ago = now-dt.timedelta(hours=24)
strftime = "%H:%M %m/%d/%Y"
created = 'origin_path'
dest = 'receiving_path'
file_path = 'file:///'+os.getcwd()+'/' + ''
print("Last modified: %s" % time.ctime(os.path.getmtime(file_path)))
print("Created: %s" % time.ctime(os.path.getctime(file_path)))
for root, dirs,files in os.walk(origin_path):
for fname in files:
path = os.path.join(root, fname)
st = os.stat(path)
mtime = dt.datetime.fromtimestamp(st.st_mtime)
if mtime > ago:
print("True: ", fname, " at ", mtime.strftime("%H:%M %m/%d/%Y"))
shutil.move(path, dest)
def find_info(): #this first func. works fine.for root, dirs, files in os.walk(created):
for root, dirs, files in os,walk(origin_path):
for fname in files:
path = os.path.join(root, fname)
st = os.stat(path)
mtime = dt.datetime.fromtimestamp(st.st_mtime)
if mtime > ago:
print(True)
else:
print(False)
print (find_info())
print (move())
print (os.listdir(dest))
print (os.listdir(created))
The problem is that you are calling os.walk with a tkinter StringVar, but os.walk does not accept StringVars; it only accepts objects of type str, bytes, or os.PathLike (e.g. pathlib Path objects).
You can fix the error by using os.walk(origin_path.get()) instead of os.walk(origin_path). This gets the string from the StringVar and passes that to os.walk, instead of passing the StringVar to os.walk directly.

Expecting string, bytes, or os.PathLike or integer, not StringVar

I'm working on a project that monitors two selected folders and automatically moves files created or edited within the last twenty-four hours from Folder_A to Folder_B. It also will check the two folders manually when the user clicks the scan button. So far it will select the two folders, but when I click the scan button I get this error. How would I go about fixing the error?
My code is below the error. Please be understanding that I am still really new to python, so there might be quite a few really stupid mistakes in here.
import tkinter as tk
from tkinter import *
from tkinter import filedialog
import os,time
import datetime
import shutil
import datetime as dt
def browse_button():
# Allow user to select a directory and store it in global var
# called origin_path
global origin_path
filename = filedialog.askdirectory()
origin_path.set(filename)
print(filename)
def browse_button2():
# Allow user to select a directory and store it in global var
# called receiving_path
global receiving_path
filename = filedialog.askdirectory()
receiving_path.set(filename)
print(filename)
def submitFunction() :
for root, dirs,files in os.walk(origin_path.get()):
for fname in files:
path = os.path.join(fname, root)
st = os.stat(path)
mtime = dt.datetime.fromtimestamp(st.st_mtime)
shutil.move(path, receiving_path)
print('Submit button is clicked.')
root = Tk()
origin_path = StringVar()
receiving_path = StringVar()
#First Browse Button Label
lbl1 = Label(master=root,textvariable=origin_path)
lbl1.grid(row=0, column=1)
#Second Browse Button Label
lbl1_2 = Label(master=root,textvariable=receiving_path)
lbl1_2.grid(row=1, column=1)
lbl1_3 = Label(master=root)
lbl1_3.grid(row=2, column=1)
button = Button(text="Browse", command=browse_button)
button.grid(row=0, column=3)
button2 = Button(text="Browse", command=browse_button2)
button2.grid(row=1, column=3)
scan_btn=Button(text="Scan", command = lambda:submitFunction())
scan_btn.grid(row=2, column=7)
mainloop()
now = dt.datetime.now()
ago = now-dt.timedelta(hours=24)
strftime = "%H:%M %m/%d/%Y"
created = 'origin_path'
dest = 'receiving_path'
file_path = 'file:///'+os.getcwd()+'/' + ''
print("Last modified: %s" % time.ctime(os.path.getmtime(file_path)))
print("Created: %s" % time.ctime(os.path.getctime(file_path)))
for root, dirs,files in os.walk(origin_path.get()):
for fname in files:
path = os.path.join(root, fname)
st = os.stat(path)
mtime = dt.datetime.fromtimestamp(st.st_mtime)
if mtime > ago:
print("True: ", fname, " at ", mtime.strftime("%H:%M %m/%d/%Y"))
shutil.move(path, dest)
def find_info(): #this first func. works fine.for root, dirs, files in os.walk(created):
for root, dirs, files in os,walk(origin_path.get()):
for fname in files:
path = os.path.join(root, fname)
st = os.stat(path)
mtime = dt.datetime.fromtimestamp(st.st_mtime)
if mtime > ago:
print(True)
else:
print(False)
print (find_info())
print (move())
print (os.listdir(dest))
print (os.listdir(created))
Here's the error:
C:/Users/quirk/PycharmProjects/Trial_2
C:/Users/quirk/PycharmProjects/Trial_2/.idea
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\quirk\AppData\Local\Programs\Python\Python310\lib\tkinter\__init__.py", line 1921, in __call__
return self.func(*args)
File "C:\Users\quirk\AppData\Local\Programs\Python\Python310\Projects\File_transfer.py", line 63, in <lambda>
scan_btn=Button(text="Scan", command = lambda:submitFunction())
File "C:\Users\quirk\AppData\Local\Programs\Python\Python310\Projects\File_transfer.py", line 39, in submitFunction
shutil.move(path, receiving_path)
File "C:\Users\quirk\AppData\Local\Programs\Python\Python310\lib\shutil.py", line 791, in move
if os.path.isdir(dst):
File "C:\Users\quirk\AppData\Local\Programs\Python\Python310\lib\genericpath.py", line 42, in isdir
st = os.stat(s)
TypeError: stat: path should be string, bytes, os.PathLike or integer, not StringVar
As the message says, receiving_path is a StringVar object, not a string. To fetch the string value, you need to use .get():
shutil.move(path, receiving_path.get())

tkinter drop down menu from excel

I want to use tkinter to browse an excel sheet and make a drop down menu of the rows of that excel sheet.
I am pretty new to python and do not know how to work it through. The code until now looks like this:
import xlrd
import os
from subprocess import call
import Tkinter,tkFileDialog
root = Tkinter.Tk()
root.withdraw()
filename = tkFileDialog.askopenfiles(title='Choose an excel file')
print(filename)
print type(filename)
#file = str(filename)
file = [filetypes for filetypes in filename if ".xlsx" in filetypes]
workbook = xlrd.open_workbook(filename)
for file in filename:
sheet = workbook.sheet_by_index(0)
print(sheet)
for value in sheet.row_values(0):
print(value)
This throws an error:
Traceback (most recent call last):
File "C:/Geocoding/test.py", line 14, in
workbook = xlrd.open_workbook(filename)
File "C:\Python27\ArcGIS10.3\lib\site-packages\xlrd__init__.py", line 394, in open_workbook
f = open(filename, "rb")
TypeError: coercing to Unicode: need string or buffer, list found
I am not even able to read the excel sheet that the user browses. I have no idea why this error. I would really appreciate if anybody can help me with it. Am I on the right path ?
Thanks
The new code that works:
import xlrd
from Tkinter import *
import Tkinter,tkFileDialog
root = Tkinter.Tk()
root.withdraw()
filename = tkFileDialog.askopenfilename(title='Choose an excel file')
print(filename)
print type(filename)
#file = str(filename)
file = [filetypes for filetypes in filename if ".xlsx" in filetypes]
workbook = xlrd.open_workbook(filename)
#for file in filename:
sheet = workbook.sheet_by_index(0)
print(sheet)
for value in sheet.row_values(0):
print(value)
print(type(value))
master = Tk()
variable=StringVar(master)
#variable=sheet.row_values(0)[0]
variable.set(sheet.row_values(0)[0])
#for var in value:
# variable = StringVar(master)
# variable.set(value) # default value
#w = OptionMenu(master, variable, value)
w = apply(OptionMenu, (master, variable) + tuple(sheet.row_values(0)))
w.pack()
mainloop()
You may have more errors along the way but in your code here:
filename = tkFileDialog.askopenfiles(title='Choose an excel file')
the result from that dialog is a list of file objects. So you are passing that list of fileobjects to open_workbook here:
workbook = xlrd.open_workbook(filename)
Instead what you need to do is pass the name of the file you care about as a string to open_workbook:
workbook = xlrd.open_workbook(filename[0].name) # the name of the first file in the list
here is a working Python3 (sorry I abandoned Python2) example for tkinter to properly select filenames:
from tkinter import filedialog
from tkinter import *
root = Tk()
root.withdraw()
filename = filedialog.askopenfiles(title='Choose an excel file')
print(filename) # filename is a list of file objects
print(filename[0].name) # this is the name of the first selected in the dialog that you can pass to xlrd

How to write(save) files to a directory instead of desktop?

Here is my code:
f = open("myfile.txt")
f.write("Writing something")
f.close()
plt.savefig('plot1.png')
plt.savefig('plot2.png')
workbook = xlsxwriter.Workbook('results.xlsx')
workbook.close()
At the moment, these files are being saved to my desktop. How would i save them to a file that the user specifies the name for? So i would have a widget like so:
self.directoryname= tkinter.Entry(self.master)
self.directoryname["width"] = 60
self.directoryname.focus_set()
self.directoryname.grid(row=1, column=1)
foldername = (self.directoryname.get())
How can i take foldername and create a directory with that name, and store the files in there?
Use the os.path.join() function and if you want to create a folder os.makedirs()
import os
path = "some/path/to/location"
foldername = (self.directoryname.get())
file_path = os.path.join(path,foldername)
os.makedirs(file_path)
filename = 'results.xlsx'
full_path = os.path.join(file_path,filename)
workbook = xlsxwriter.Workbook(full_path)
workbook.close()

Categories

Resources