Renaming files with python results in duplicate files - python-3.x

I have a folder with the following files:
[11111]Text.txt
[22222]Text.txt
[33333]Text.txt
[44444]Text.txt
I need rename the files to remove the [11111] designation from the beginning of the file name, however that results in duplicate file names.
I wrote a basic script out that will strip the [11111] from the first file, and if any duplication occurs with subsequent files it will name the file [Duplicate]_[#]_text.txt where [#] is a random number
When I ran the code, it renamed the first file correctly, and renamed the second file with the required string, but it did not continue with the other files, and instead presented the following error:
FileExistsError: [WinError 183] Cannot create a file when that file already exists: 'Destination/[33333]Text.txt' -> 'Destination/[Duplicate]_[1]Text.txt'
The code below is what I have currently, though i have tried several iterations also
Location = (Destination_Folder)
Dupe_Counter = random.randint(0,255)
for filename in os.listdir(Location):
try:
if filename.startswith("["):
os.rename(Location + filename, Location + filename[7:])
except:
os.rename(Location + filename, Location +'[Duplicate]_' + '[' + str(Dupe_Counter) +']' + filename[7:])
I'm assuming that it's not actually picking up the Dupe_Counter when creating new files, however I'm not 100% sure where i'm going wrong.
Any help appreciated.

In your Dupe_Counter you are generating a random number that can collide with the results sometimes. But on top of that, you are generating the random Dupe_Counter once only.
Try to generate a random number for each iteration.
Location = (Destination_Folder)
for filename in os.listdir(Location):
Dupe_Counter = random.randint(0,255)
try:
if filename.startswith("["):
os.rename(Location + filename, Location + filename[7:])
except:
os.rename(Location + filename, Location +'[Duplicate]_' + '[' + str(Dupe_Counter) +']' + filename[7:])
But I would recommend generating an increasing sequence for renaming the files and better understanding.
Something Like this:
Location = (Destination_Folder)
for filename in os.listdir(Location):
Dupe_Counter = 101
try:
if filename.startswith("["):
os.rename(Location + filename, Location + filename[7:])
except:
os.rename(Location + filename, Location +'[Duplicate]_' + '[' + str(Dupe_Counter) +']' + filename[7:])
Dupe_Counter += 1
Hope I've been of some help.

Related

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

Python3 _io.TextIOWrapper error when opening a file with notepad

I am stuck from a couple of days on an issue in my micro Address Book project. I have a function that writes all records from a SQLite3 Db on file in order to open in via OS module, but as soon as I try to open the file, Python gives me the following error:
Error while opening tempfile. Error:startfile: filepath should be string, bytes or os.PathLike, not _io.TextIOWrapper
This is the code that I have to write records on file and to open it:
source_file_name = open("C:\\workdir\\temp.txt","w")
#Fetching results from database and storing in result variable
self.cur.execute("SELECT id, first_name, last_name, address1, address2, zipcode, city, country, nation, phone1, phone2, email FROM contacts")
result = self.cur.fetchall()
#Writing results into tempfile
source_file_name.write("Stampa Elenco Contatti\n")
for element in result:
source_file_name.write(str(element[0]) + "|" + str(element[1]) + "|" + str(element[2]) + "|" + str(element[3]) + "|" + str(element[4]) + "|" + str(element[5]) + "|" + \
str(element[6]) + "|" + str(element[7]) + "|" + str(element[8]) + "|" + str(element[9]) + "|" + str(element[10]) + "|" + str(element[11]) + "\n")
#TODO: Before exiting printing function you MUST:
# 1. filename.close()
# 2. exit to main() function
source_file_name.close()
try:
os.startfile(source_file_name,"open")
except Exception as generic_error:
print("Error while opening tempfile. Error:" + str(generic_error))
finally:
main()
Frankly I don't understand what this error means, in my previous code snippets I've always handled text files without issues, but I realize this time it's different because I am picking my stream from a database. Any ideas how to fix it?
Thanks in advance, and sorry for my english...
Your problem ultimately stems from poor variable naming. Here
source_file_name = open("C:\\workdir\\temp.txt","w")
source_file_name does not contain the source file name. It contains the source file itself (i.e., a file handle). You can't give that to os.startfile(), which expects a file path (as the error also says).
What you meant to do is
source_file_name = "C:\\workdir\\temp.txt"
source_file = open(source_file_name,"w")
But in fact, it's much better to use a with block in Python, as this will handle closing the file for you.
It's also better to use a CSV writer instead of creating the CSV manually, and it's highly advisable to set the file encoding explicitly.
import csv
# ...
source_file_name = "C:\\workdir\\temp.txt"
with open(source_file_name, "w", encoding="utf8", newline="") as source_file:
writer = csv.writer(source_file, delimiter='|')
source_file.write("Stampa Elenco Contatti\n")
for record in self.cur.fetchall():
writer.writerow(record)
# alternative to the above for loop on one line
# writer.writerows(self.cur.fetchall())

files are saved repeatedly with single name, no looping, no ranging

My codes runs well, but have one flaw. They are not saving accordingly. For example, Let's say I caught 3 jpeg files, when I ran the codes, it saves 3 times on slot 1, 3 times on slot 2, and 3 times on slot 3. So I ended up with 3 same files.
I think there is something wrong with my looping logic?
If I changed for n in range(len(soup_imgs)): to for n in range(len(src)):, the operation saves infinitely of the last jpeg files.
soup_imgs = soup.find(name='div', attrs={'class':'t_msgfont'}).find_all('img', alt="", src=re.compile(".jpg"))
for i in soup_imgs:
src = i['src']
print(src)
dirPath = "C:\\__SPublication__\\"
img_folder = dirPath + '/' + soup_title + '/'
if (os.path.exists(img_folder)):
pass
else:
os.mkdir(img_folder)
for n in range(len(src)):
n += 1
img_name = dirPath + '/' + soup_title + '/' + str({}).format(n) + '.jpg'
img_files = open(img_name, 'wb')
img_files.write(requests.get(src).content)
print("Outputs:" + img_name)
I am amateur in coding, just started not long ago as a hobby of mine. Please give me some guidance, chiefs.
Try this when you are writing your image files:
from os import path
for i, img in enumerate(soup_imgs):
src = img['src']
img_name = path.join(dirPath, soup_title, "{}.jpg".format(i))
with open(img_name, 'wb') as f:
f.write(requests.get(src).content)
print("Outputs:{}".format(img_name))
You need to loop over all image sources, rather than using the last src value from a previous for block.
I've also added a safer method for joining directory and file paths that should be OS independent. Finally, when opening a file, always use the with open() as f: construct - this way Python will automatically close the filehandle for you.

adding creation time to a files filename

So far I have the following:
source_folder = 'file_location'
for file in os.listdir(source_folder):
if file.startswith('stnet_'):
os.rename(file, file.replace('stnet_a_b', '%s_' % time.ctime(os.path.getctime(file)) + 'stnet_a_b'))
The issue with is is I keep getting FileNotFoundError: [WinError 2] The system cannot find the file specified 'stnet_a_b.raw'
Can someone point out what I'm doing wrong?
Thanks.
os.listdir can only get the filenames without directory, while os.rename, os.path.getctime needs full name with directory(if your current directory is not conincidently file_location then the file will not be found).
You can use os.path.join to get the full name. And if you are on Windows you must make sure filename doesn't contain special characters which your code contains.
dir = r'file_location'
# os.chdir(dir) # in case you don't want to use os.path.join
for filename in os.listdir(dir):
print(filename)
if filename.startswith('stnet_'):
src = os.path.join(dir, filename)
ctime_str = str(time.ctime(os.path.getctime(src)))
ctime_str = ctime_str.replace(':', '').replace(' ', '') # remove special characters
fn_new = filename.replace('stnet_a_b',
'{}_'.format(ctime_str + 'stnet_a_b'))
des = os.path.join(dir, fn_new)
print('src={}, des={}'.format(src, des))
os.rename(src, des)
please try above code.

Renaming, Moving, and Deleting Original Directory

I'm trying to right a script that will walk through a given directory and rename, move, and delete the original directory. Each directory has a *.mp4 file and a subfolder containing *.jpg files. I'm having trouble deleting the original directory when I'm done renaming and moving the files. What so far is:
import datetime, os, re, shutil, logging, smtplib
logging.basicConfig(level = logging.INFO, format = ' %(asctime)s - %(levelname)s - %(message)s')
#logging.disable(logging.info)
path = '\\\\RT-N66U\\sda2\\Documents'
desired_text1 = re.compile(r'^\d{3}_[a-zA-Z]+\d{3}.jpg')
desired_text2 = re.compile(r'^\d{3}_[a-zA-Z]+_\d{3}.jpg')
renamed_files = ''
for folderName, subfolders, filenames in os.walk(path):
if folderName.startswith(path + '\\GEO-'):
logging.info('The current folder is ' + folderName)
for subfolder in subfolders:
if subfolder.startswith('Pics'):
pic_folder = subfolder
for filename in filenames:
if filename.endswith('.mp4'):
changed_date = datetime.datetime.strptime(filename[3:17], '%b %d, %Y').strftime('%y.%m.%d') # Changes the name of the date to the desired format
year = datetime.datetime.strptime(filename[3:17], '%b %d, %Y').strftime('%Y')
name = filename[20:-25]
name = name.lower()
modified_name = '.'.join(re.findall('\S+', name))
final_name = 'geo.' + changed_date + '.' + modified_name
if not os.path.exists('\\\\RT-N66U\\sda2\\Me\\GEO\\%s\\%s\\%s' % (year, changed_date[3:5], final_name)):
os.makedirs('\\\\RT-N66U\\sda2\\Me\\GEO\\%s\\%s\\%s' % (year, changed_date[3:5], final_name))
if not os.path.exists('\\\\RT-N66U\\sda2\\Me\\GEO\\%s\\%s\\%s\\%s' % (year, changed_date[3:5], final_name, pic_folder)):
os.makedirs('\\\\RT-N66U\\sda2\\Me\\GEO\\%s\\%s\\%s\\%s' % (year, changed_date[3:5], final_name, pic_folder))
if filename.endswith('.mp4'):
logging.info(filename)
os.rename(folderName + '\\' + filename, '\\\\RT-N66U\\sda2\\Me\\GEO\\%s\\%s\\%s\\%s.mp4' % (year, changed_date[3:5], final_name, final_name))
# This part will logg and rename the files by adding a '_'
mo1 = desired_text1.search(filename)
mo2 = desired_text2.search(filename)
if mo1:
logging.info(folderName + '\\' + filename)
os.rename(folderName + '\\' + filename, '\\\\RT-N66U\\sda2\\Me\\GEO\\%s\\%s\\%s\\%s\\%s_%s' % (year, changed_date[3:5], final_name, pic_folder, filename[:-7], filename[-7:]))
renamed_files += filename + ' -> ' + filename[:-7] + '_' + filename[-7:] + '\n'
elif mo2:
logging.info(folderName + '\\' + filename)
os.rename(folderName + '\\' + filename, '\\\\RT-N66U\\sda2\\Me\\GEO\\%s\\%s\\%s\\%s\\%s' % (year, changed_date[3:5], final_name, pic_folder, filename))
renamed_files += filename + '\n'
# This part will check if the directory is empty and delete it if so
if os.listdir(folderName) == []:
logging.info(folderName)
shutil.rmtree(folderName)
What ends up happening is that all sub-directories will be deleted if they're empty and leaving the primary directory empty. I would like the primary directory to be removed as well, since all the files have been moved. Is there a way to accomplish this within the for statement?
If you mean deleting the directory known as folderName inside your main for loop, I think it's not really possible since you're iterating over an object that contains it. Like if inside a for i in this_list: you would like to remove an object from this_list. This is not possible before you're out of the loop.
In order to achieve what you want, I would write a function to recurse into the folder tree. The idea would be something like:
def process_folder(folder_name):
do some stuff on files
get the subfolders of folder_name
for f in subfolders:
process_folder(subfolder_name)
if subfolder_name is empty, delete it
maybe do some other stuff on files
and in the main script, call process_folder(path). (This would leave only the top folder there even if it's empty though, so be sure you don't want to delete it; or to call process_folder at a higher level, or to add an instruction to delete it too if it's empty).

Resources