shutil.copy fails after os.makedirs - python-3.x

so as you can see im trying to create a small backup script for my self, to select needed files and back them up.
import shutil
import datetime
import os
import time
def backup():
# set the update interval
while True:
backup_interval = input("Please enter the backup interval in seconds: ") # 300
try:
valid_time = int(backup_interval) // 60
print("Backup time set to:", valid_time, "minutes!")
break
except ValueError:
print("This time is not valid, please enter a correct time in seconds: ")
print(">>> 60 seconds = 1 minute, 3600 seconds = 60 minutes.")
backup_file = input(r"Please enter the path for the file to backup: ") # D:\Python\BackupDB\test.db"
dest_dir = input(r"Please enter the destination path: ") # D:\Python\BackupDB\
folder_name = input(r"Please name your backup folder: ") # BD_Backup
now = str(datetime.datetime.now())[:19]
now = now.replace(":", "_")
# backup_file = backup_file.replace(backup_file, backup_file + str(now) + ".db")
# thats why I got the FileNotFoundError
final_destination = os.path.join(dest_dir, folder_name)
if not os.path.exists(final_destination):
os.makedirs(final_destination)
print("hello world")
shutil.copy(backup_file, final_destination)
the first question is, how do i replace the name after i copied the file into the destination folder to get something like that test.db -> test_2020-02-23 08_36_22.db
like here :
source_dir = r"D:\Python\BackupDB\test.db"
destination_dir = r"D:\Python\BackupDB\BD_Backup\test_" + str(now) + ".db"
shutil.copy(source_dir, destination_dir)
output :
test_2020-02-23 08_36_22.db
what im doing wrong here?
and how to copy the file 5 times and after a while (backup_interval) delete the first one and move the last 4 up and create a new one so I have in total 5 copies of that file?

I have modified your code as you need,
backup_file = input(r"Please enter the path for the file to backup: ") # D:\Python\BackupDB\test.db"
dest_dir = input(r"Please enter the destination path: ") # D:\Python\BackupDB\
folder_name = input(r"Please name your backup folder: ") # BD_Backup
old_file_name=backup_file.split("/")[-1]
now = str(datetime.datetime.now())[:19]
now = now.replace(":", "_")
new_file_name = old_file_name.split(".")[0]+"_" + str(now) + ".db"
final_destination = os.path.join(dest_dir, folder_name)
if not os.path.exists(final_destination):
os.mkdir(final_destination)
new_file="/"+new_file_name
shutil.copy(backup_file, final_destination)
os.rename(final_destination+'/'+old_file_name,final_destination+new_file)
I did like , after copy the file, i just rename it

I've ran into a similar problem before and the reason was that the creation of the directory hadn't completed yet before trying to access it. A simple sleep before the copy should be able to confirm this.

Related

Python Selenium: Check if a new file in the download folder is added

I have this when I press on a link it downloads to the download folder.
my Url looks something like so
url='https://vle......ac.uk/pluginfile.php/2814969/mod_page/content/16/Statistics_for_Business_and_Economics_----_%28Unit_I_Introduction%29.pdf'
driver.execute_script("window.open('%s', '_blank')" % URL)
Where the URL is a pdf file that I am trying to download.
I want to write a code that waits until number of files in the download folder increases to move on to the next itteration in the loop.
I wrote this code:
def wait_till_number_of_files_is_byound_the_current_file():
path_download=r'\\Mac\Home\Downloads\*'
list_of_files = glob.glob(path_download)
a=len(list_of_files)
while len(list_of_files)==a:
time.sleep(1)
list_of_files = glob.glob(path_download)
In my for loop I also tried this code
item = WebDriverWait(driver, 10).until(lambda driver: driver.execute_script("window.open('%s', '_blank')" % URL))
but this made the file being pressed infinitely not only once.
The best way, to get around this (I hope there would be a better way) is to use the following function
def download_wait(directory, timeout, nfiles=None):
"""
Wait for downloads to finish with a specified timeout.
Args
----
directory : str
The path to the folder where the files will be downloaded.
timeout : int
How many seconds to wait until timing out.
nfiles : int, defaults to None
If provided, also wait for the expected number of files.
"""
seconds = 0
dl_wait = True
while dl_wait and seconds < timeout:
time.sleep(1)
dl_wait = False
files = os.listdir(directory)
if nfiles and len(files) != nfiles:
dl_wait = True
for fname in files:
if fname.endswith('.crdownload'):
dl_wait = True
seconds += 1
return seconds
In my for loop, I wrote the following
for url in hyper_link_of_files:
# Click on this link
driver.execute_script("window.open('%s', '_blank')" % url)
# time.sleep(2)
download_wait(r'\\Mac\Home\Downloads', 10, nfiles=None)
time.sleep(2)
# move the last download file into the destination folder
Move_File(dest_folder)
I will share my Move_File function for reference to those who are interested in moving the downloaded file into a new destination
def Move_File(path_needed):
# Get the working directory of the downloads folder
path_download=r'\\Mac\Home\Downloads\*'
list_of_files = glob.glob(path_download)
latest_file = max(list_of_files, key=os.path.getctime)
# Copy to the new file into the destination
path_destination=os.path.join(path_needed,os.path.basename(latest_file))
shutil.move(latest_file,path_destination)

want to count if a file exists and store a duplicate followed by a copy number on python

I want to make a script that monitors changes in a folder and moves files to special directories. I use pip-watchdog
from watchdog.events import FileSystemEventHandler
def makeUnique(path,counter):
filename, extension = os.path.splitext(path)
# IF FILE EXISTS, ADDS NUMBER TO THE END OF THE FILENAME
file_split=filename.split('\\')
new_name="DUPLICATE_"+file_split[-1]
new_file=file_split[-1].replace(file_split[-1],new_name)
while os.path.exists(path):
path = new_file + " (" + str(counter) + ")" + extension
counter += 1
return path
def move(dest, entry, name):
"""dest = D:\Download\ChromeSetup.exe"""
file_exists = os.path.exists(dest + "\\" + name)
counter=1
if file_exists:
unique_name = makeUnique(entry,counter)
dest = dest+"\\"+unique_name
os.rename(entry, dest)
try:
print(f'[magenta][[/] [indian_red1 bold]{name}[/] [magenta]][/] -> [magenta][[/]
[orange_red1 bold]{dest}[/] [magenta]][/] to ' + f'[dark_orange]{dest}[/]')
shutil.move(entry,dest)
except:
pass
def moveByExtension(str, dest_dir, entry, name):
if name.endswith(str):
dest = dest_dir
move(dest, entry, name)
dest_dir_exe = r'D:\Download\exe_files'
class MoverHandler(FileSystemEventHandler):
def on_created(self, event):
"""when a file or directory is created"""
with os.scandir(source_dir) as entries:
for entry in entries:
name = entry.name
# app
moveByExtension('.exe', dest_dir_exe, entry, name)
My current filesystem tree:
-Download/
-- ChromeSetup.exe (rename and move to exe_files)
-Download/exe_files/
-- ChromeSetup.exe
-- DUPLICATE_ChromeSetup (1).exe
But if ChromeSetup.exe is in the download again, then the error occurs 'DUPLICATE_ChromeSetup (1).exe' already exists, although 'DUPLICATE_ChromeSetup (2).exe' is expected.
want to count if a file exists and store a duplicate followed by a copy number
I'm learning python at the moment...maybe I don't see the obvious problem
thank you in advance

Find folders that has no data in it and get their folder names

I want to find folders that has no data in it and get thier folder names.
The first and second folders are named randomly in numbers and has data in random folders.
the codes are
path = 'M://done/mesh/*'
FL = glob.glob(path)
FL2 = glob.glob(FL[0] + '/*')
FL2
['M://done/mesh\\41\\23',
'M://done/mesh\\41\\24',
'M://done/mesh\\41\\33',
'M://done/mesh\\41\\34',
'M://done/mesh\\41\\35',
'M://done/mesh\\41\\36',
'M://done/mesh\\41\\43',
'M://done/mesh\\41\\44',
'M://done/mesh\\41\\45',
'M://done/mesh\\41\\46',
'M://done/mesh\\41\\47',
'M://done/mesh\\41\\53',
'M://done/mesh\\41\\54',
'M://done/mesh\\41\\55',
'M://done/mesh\\41\\63',
'M://done/mesh\\41\\64',
'M://done/mesh\\41\\65',
'M://done/mesh\\41\\66',
'M://done/mesh\\41\\67',
'M://done/mesh\\41\\74',
'M://done/mesh\\41\\75',
'M://done/mesh\\41\\76',
'M://done/mesh\\41\\77',
'M://done/mesh\\41\\85',
'M://done/mesh\\41\\86',
'M://done/mesh\\41\\87']
FL2[24][24:26] + FL2[24][27:30] + '0000' # why do I need [24:26}, [27:30]???
finding_files = ['_Caminfo.dat','running.csv']
print(FL2[0] + '/0000/02_output/' + FL2[0][24:26] + FL2[0][27:30] + '0000/' + fn1[0])
'41860000'
You can use os.listdir to find empty folders, like below:
import os
folder_list = ["D:\\test_1", "D:\\test_2"]
empty_folders = []
for folder in folder_list:
try:
if not os.listdir(folder):
empty_folders.append(folder)
except FileNotFoundError:
pass
print(empty_folders)

Run code on specific files in a directory separately (by the name of file)

I have N files in the same folder with different index numbers like
Fe_1Sec_1_.txt
Fe_1Sec_2_.txt
Fe_1Sec_3_.txt
Fe_2Sec_1_.txt
Fe_2Sec_2_.txt
Fe_2Sec_3_.txt
.
.
.
and so on
Ex: If I need to run my code with only the files with time = 1 Sec, I can make it manually as follow:
path = "input/*_1Sec_*.txt"
files = glob.glob(path)
print(files)
which gave me:
Out[103]: ['input\\Fe_1Sec_1_.txt', 'input\\Fe_1Sec_2_.txt', 'input\\Fe_1Sec_3_.txt']
In case of I need to run my code for all files separately (depending on the measurement time in seconds, i.e. the name of file)
I tried this code to get the path for each time of measurement:
time = 0
while time < 4:
time += 1
t = str(time)
path = ('"input/*_'+t+'Sec_*.txt"')
which gives me:
"input/*_1Sec_*.txt"
"input/*_2Sec_*.txt"
"input/*_3Sec_*.txt"
"input/*_4Sec_*.txt"
After that I tried to use this path as follow:
files = glob.glob(path)
print(files)
But it doesn't import the wanted files and give me :
"input/*_1Sec_*.txt"
[]
"input/*_2Sec_*.txt"
[]
"input/*_3Sec_*.txt"
[]
"input/*_4Sec_*.txt"
[]
Any suggestions, please??
I think the best way would be to simply do
for time in range(1, 5): # 1,2,3,4
glob_path = 'input/*_{}Sec_*.txt'.format(time)
for file_path in glob.glob(glob_path):
do_something(file_path, measurement) # or whatever

Script to rename and copy files to a new directory.

Hi I have recently made this script to rename files I scan for work with a prefix and a date. It works pretty well however it would be great if it could make a directory in the current directory with the same name as the first file then move all the scanned files there. E.g. First file is renamed to 'Scanned As At 22-03-2012 0' then a directory called 'Scanned As At 22-03-2012 0' (Path being M:\Claire\Scanned As At 22-03-2012 0) is made and that file is placed in there.
I'm having a hard time figuring out the best way to do this. Thanks in advance!
import os
import datetime
#target = input( 'Enter full directory path: ')
#prefix = input( 'Enter prefix: ')
target = 'M://Claire//'
prefix = 'Scanned As At '
os.chdir(target)
allfiles = os.listdir(target)
count = 0
for filename in allfiles:
t = os.path.getmtime(filename)
v = datetime.datetime.fromtimestamp(t)
x = v.strftime( ' %d-%m-%Y')
os.rename(filename, prefix + x + " "+str(count) +".pdf")
count +=1
Not quite clear about your requirement. If not rename the file, only put it under the directory, then you can use the following codes (only the for-loop of your example):
for filename in allfiles:
if not os.isfile(filename): continue
t = os.path.getmtime(filename)
v = datetime.datetime.fromtimestamp(t)
x = v.strftime( ' %d-%m-%Y')
dirname = prefix + x + " " + str(count)
target = os.path.join(dirname, filename)
os.renames(filename, target)
count +=1
You can check help(os.renames).

Resources