Creating A Loop To Hash The Contents of An Entire Folder - python

I'm brand new to this website (and coding as a whole) and have been trying to find a way to successfully hash the contents of a folder and plop all the hashes into a .csv!
Below is a picture of what I have so far! Again, I know it leaves a lot of room to be desired... but it functions at the very least! The biggest problem I'm having right now is ensuring that every file in the folder, rather than just the folder itself, is being hashed and put into the .csv file.
Edit: For clarity, my hope is to be able to do the following:
Ask the user which folder of files they would like to hash, and verify that the folder exists (done).
Next verify where the user would like to have the hashes output to (done).
Then have the program hash all the files included in the target folder, and list all of the hash values in a CSV in the location chosen by the user.
Currently I believe the program does the first two, but instead of hashing all the files in the folder it instead hashes the folder itself. I'm not really sure how to make the program instead target all the files and write their hashes into a single csv file rather than just hashing the folder.
Thank you again for any help in advance!
What I have So Far
import os
import hashlib
import os.path
def main():
print('Kurtis\'s SHA-256 Hashing Program')
print(f'Note: Please make sure in insert the entire folder directory! ex: C:\Data\Hashme\Yeehaw')
folderd = input('What is the directory of the folder that contains the files you would like to hash?: ')
if os.path.exists(folderd):
os.chdir(folderd)
print(f'Thank you for selecting a folder! The folder you have chosen to hash can be found at {folderd}')
hashlocation = input('Which folder would you like your hash output to be stored in: ')
while os.path.exists(hashlocation):
verification = input(f'Excellent! {hashlocation} exists. Are you sure this is where you\'d like to store your hashed files (Y/N)?')
if verification == 'Yes' or verification == 'yes' or verification == 'y' or verification == 'Y':
def update_kurt(folderd, kurt):
with open(folderd, 'rb') as f:
while True:
block = f.read(2 ** 10) # Magic number: one-megabyte blocks.
if not block:
break
kurt.update(block)
for (path, dirs, files) in os.walk('.'):
kurt = hashlib.sha256()
for file in files:
fullpath = os.path.join(path, file)
update_kurt(fullpath, kurt)
os.chdir(hashlocation)
with open('SHA-256.CSV', 'w') as f:
f.write(kurt.hexdigest())
print(f'Congratulations! Your hash for the folder {folderd} was successful and can be found in {hashlocation}. You will now be taken back to the beginning so that you might be able to hash further files if you so desire.')
os.chdir(folderd)
f.close()
main()
else:
print(f'Apologies! I am either too dumb to infer meaning from your response "{verification}" or you responded in the non-affirmative. For the sake of my creator\'s grade I will take you back to the beginning to start over!')
main()
else:
newdir = input(f'I\'m sorry! {hashlocation} does not currently exist. Would you like to create a new folder at that directory?(Y/N)')
if newdir == 'Yes' or newdir == 'Y' or newdir == 'yes' or newdir == 'y':
os.mkdir(hashlocation)
print(f'Wonderful! Your new folder "{hashlocation}" has been created. You will now be looped back to the beginning to create your desired hash files.')
main()
else:
print('Sounds good! I\'ll just loop you back to the beginning!')
main()
else:
print(f'{folderd} does not exist, please try again.')
main()
if __name__ == '__main__':
main()

Related

Python - Input() multiple file paths at once and append in a list

I am writing a code to zipFile multiple files based on user's input.
For example, user type couple file paths such as C:\Users\AAA\BBB, C:\Users\AAA\CCC,... The program will back up all these files into one single new zipFile.
Right now I'm using a loop (the code from "While True") and it works. But this only allows us to enter one path each time. Is there a neat way that we can input all the path at once and add each of them in a list (fileList here)?
And as I just started Python and I wrote it based on "A Byte of Python", I feel my code is kind of lengthy... Please feel free to provide recommendation to improve it. Thank you.
import os,time,zipfile
def createZip():
# Define the file path to save the file
savePath=input('Enter file save path-->')
if len(savePath)==0:
print('No path is found. Backup ends.')
# Define the file to be saved
else:
assert os.path.exists(savePath),"File path does not exist. Backup fails." # assert expression1, expression2, equals to if not expression1, raise AssertionError(expression2)
fileList=[]
while True:
filePath=input('Enter files to save. Enter "Done" to end.-->')
if filePath=='Done':
break
else:
if len(filePath)==0:
print('No path is found. Please enter files to save.')
else:
assert os.path.exists(filePath),"File path does not exist. Backup fails."
fileList.append(filePath)
today=savePath+os.sep+time.strftime('%Y%m%d')
now=time.strftime('%H%M%S')
if not os.path.exists(today):
os.mkdir(today)
print('Successfully created directory', today)
comment=input('Enter a comment -->')
if len(comment)==0:
target=today+os.sep+now+'.zip'
else:
target=today+os.sep+now+'_'+comment+'.zip'
newZip=zipfile.ZipFile(target,'w',zipfile.ZIP_DEFLATED) # 'w' means write only; 'r' means read only
for fName in fileList:
for root,dirs,files in os.walk(fName):
for file in files:
newZip.write(os.path.join(root,file))
newZip.close()
print('backup to',target)
createZip()
Its mostly easy. You can split the text the user enters, but you need to worry about files with spaces in their names. The shlex lets you split a line the same way a unix-like shell would, which gives you the rules you need.
import shlex
fileList = []
while True:
filePaths = input('Enter files to save. Enter "Done" to end.-->')
if filePaths.lower() == "done":
break
for filePath in shlex.split(filePaths):
if not os.path.exists(filePath):
print("'{}' not found".format(filePath))
else:
fileList.append(filePath)

Replacing text in set of files, and writing to new files

I have a set of .SQL scripts in a folder (maybe 20 or so files). I want to search every file in that folder and replace 'ABC' with 'ABCD' and 'XYZ' with 'WXYZ', and then take each file that's been processed and save it in a different folder (path_2) in example below, with the same file name as the original.
I know this is not working, what tweaks are needed?
import sys
def main():
path = "C:/path/to/input/folder"
path_2 = "C:/path/to/input/folder"
def replace_text(replacements):
replacements = {'ABC': 'ABCD', 'XYZ':'WXYZ'}
path_2.write()
for filename in path:
if filename.endswith('.sql')
open(filename,'r')
replace_text()
if __name__ == "__main__":
main()
you never actually get filename - you could use os.listdir(), or glob.glob("*.sql") might be easier
if filename.endswith('.sql') needs to end with a colon
below that, open and replace_text need to be indented
the contents of main need to be indented
def replace_text should not be in main
you open the file; you should then .read() the contents and pass it to replace_text
replace_text doesn't do anything; for each key,value pair in replacements.items() you should do text.replace(key, value)
replace_text should then pass the updated text back to main
main should then save the updated text
There are many syntax errors in your code. #Hugh-Bothwell pointed out those errors. Also, both paths are same.
If you want to do just these two replacements, I think there is no need to create a separate function or a dictionary.
Following code should work -
import os
def main():
path = "C:/path/to/input/folder"
path_2 = "C:/path/to/output/folder"
for filename in os.listdir(path):
if filename.endswith('.sql'):
#Getting Full file paths to read/write
full_file_path = os.path.join(path, filename)
new_file_path = os.path.join(path_2, filename)
with open(full_file_path,"r") as f:
content = f.read()
content = content.replace("ABC","ABCD").replace("XYZ","WXYZ")
'''This will save all the files to new location, even if there is no change, to save only changed files,
copy the content to a temp variable and check if there is any change before saving'''
with open(new_file_path, "w") as f_new:
f_new.write(content)
if __name__ == "__main__":
main()
Note:
The path to the new location should exist, or you can create the
path using - os.makedirs(path_2)
The replacements are case sensitive
It will replace the occurrences in between the words too, e.g MNABCS will be replaced by MNABCDS

Moving a file from one folder to another and back in Python

I'm relatively new to python and I'm working on a few projects. Say I'm running the script on partition D on Windows, so, for example, it's "D:/quarantine.py"
What I'm looking for right now is:
Taking a file from one folder (say, Desktop) and moving it to another folder (say, C:\Quarantine) - but I need to read both files and directories from the keyboard. The C:\Quarantine folder is created earlier with this code:
def create_quar(quar_folder):
try:
os.makedirs(quar_folder)
except OSError as exception:
if exception.errno != errno.EEXIST:
raise
dir_name = input("Enter the desired quarantine path: ")
if os.path.isdir(dir_name):
print ("Directory already existed.")
else:
print ("Directory created successfully!")
create_quar(dir_name)
Before moving the file, I need to store the file's previous location somehow. I was thinking of creating a .txt file in that C:\Quarantine folder.
If I ever change my mind, I call on a function that reads the .txt file I created earlier, and just moves the files back to the original folder. This, I have no idea how to implement.
I'm at a loss as to how to go about doing this. Was thinking of something like this for logging the path and moving the file:
path = input("Directory of file I need to move: ")
file = input("File name: ")
f = open(dir_name+"\log.txt",'w')
f.write(os.path.abspath(path+file))
shutil.move(path+file,dir_name+file)
dir_name is the variable I used earlier to read the Quarantine folder location, so I figured I could reuse it. As for the reading the log file and restoring, I have no idea.
Can anyone help?
You can use os.system() function by importing it from os. It will execute command in cmd/shell, but for the sub-process only.
I hope this is helpfull
Alright, so I managed to do this by myself in the end. In case anyone is interested you'll find samples of the code below. It's very rudimentary and can of course be optimized but it does work.
Main:
def Main():
dir_name = input("Enter the destination path: ")
if os.path.isdir(dir_name):
print ("Directory already existed.")
else:
print ("Directory created successfully!")
os.makedirs(dir_name)
choice = input("Would you like to (M)ove or (R)estore?: ")
if choice == 'M':
path = input("Directory of file you want moved: ")
file = input("Name of the file+extension: ")
file_path = path+'/'+file
move(file_path)
print ("Done.")
elif choice == 'R':
with open('quar_id.txt') as f:
quar_id = f.readline()
restore_from_quar(quar_id)
print ("Done.")
else:
print ("No valid option selected, closing...")
Move:
def move(filepath):
f = open('quar_id.txt','w')
f.write(path)
f.close()
os.chdir(dir_name)
shutil.move(file_path,dir_name+'/'+file)
Restore:
def restore(quar_id):
os.chdir(dir_name)
myfile = os.listdir(dir_name)
file = str(myfile)
file = file[2:-2]
shutil.move(file,quar_id+'/'+file)

Uploading multiple files via FTP based on filename

Using Python 3.4
I am generating files that are will look like 'Report_XXXXXX.xlsx' with X being unique customer numbers. I have a server with folders that are named 'XXXXXX.CustomerName'. I am trying to loop through each file/report and upload it to the matching folder based on the customer no. I have something that is working in my small test environment but I don't think it is working how I want. It uploads the files, but I am trying to catch anytime it doesn't find a match. Currently it fails my IF statment for every file. I think I am looping too many times or over the wrong items.
import os
import ftplib
creds = [line.rstrip('\n') for line in open('C:\\folder\\credentials.txt')]
ftp = ftplib.FTP_TLS("server.com")
ftp.login(creds[0], creds[1])
ftp.prot_p()
src_dir = 'C:\\Reports\\'
src_files = os.listdir('C:\\Reports\\')
for folder_name in ftp.nlst():
for file_name in src_files:
if folder_name[0:6] == file_name[7:-5]:
ftp.cwd('/'+folder_name)
open_file = open(src_dir+file_name, 'rb')
ftp.storbinary('STOR '+file_name, open_file)
open_file.close()
else:
print('Folder ' + folder_name + ' Not Found')
ftp.quit()
So for example the source directory has 3 files: 'Report_100002.xlsx, Report_100003.xlsx, Report_100007.xlsx' And the server has matching folders and a few extra folders. The files upload, and the output looks like so:
Folder 100000.CustomerName Not Found
Folder 100000.CustomerName Not Found
Folder 100000.CustomerName Not Found
Folder 100002.CustomerName Not Found
Folder 100002.CustomerName Not Found
Folder 100003.CustomerName Not Found
Folder 100003.CustomerName Not Found
Folder 100007.CustomerName Not Found
Folder 100007.CustomerName Not Found
I am trying to get to a state where I can properly log each item and whether it was a success, what folder it landed in, etc...
In your inner for loop you compare all 3 file names in src_dir with folder_name, but maximally only one satisfies the condition in your if statement. So the other 2 or 3 files that don't match cause the output you are seeing, for every folder on the ftp server. You could use a flag to keep track of whether a match was found and print your output based on that flag.
Another thing is that you should start iterating over src_files and then find matching folder names by iterating over ftp.nlist() (you are interested in source files that don't have a matching folder, not the other way around). So something like this (assuming a source file is allowed to end up in multiple folders):
....
folder_names = ftp.nlst()
for file_name in src_files:
folder_found = False
for folder_name in folder_names:
if folder_name[0:6] == file_name[7:-5]:
folder_found = True
ftp.cwd('/'+folder_name)
open_file = open(src_dir+file_name, 'rb')
ftp.storbinary('STOR '+file_name, open_file)
open_file.close()
if not folder_found:
print('No destination folder found for ' + file_name)
ftp.quit()
(the folder_names = ftp.nlst() is there so you don't repeatedly list the directories on the server)

Opening Files From Any Directory

I'm writing this basic code that runs files on my computer but right now it can only open files from the directory it is in. is there a way to open files from anywhere on my computer or would I have to give the path for the file.
Here is my code:
def run(filename):
try:
import os
os.startfile(filename)
except:
WindowsError
print ("Thats not a valid file name")
while True:
filename = raw_input("Filename: ")
run(filename)
x = raw_input("Would you like to open another file? [y/n]: ")
if x == "n":
quit()
This opens and runs the files fine but only from the directory its saved in.
def run(filename):
for directoy,files,dirs in os.walk("C:\\"):
if filename in files:
return os.startfile(os.path.join(directory,filename))
fair warning it may be slow ...
you can do this a couple of different ways
either use entire paths
or change the directory its looking at
changing the directory is pretty easy
os.chdir("PATH TO DIRECTORY")

Categories

Resources