Os.rename Files Overwrite - python

I am making a Python project that renames multiple files. However, sometimes the files overwrite.
suffixes = ['.pdf', '.epub', '.mobi']
file_list = []
def change_fname(dir_name, part=' (z-lib.org)', action='remove'):
fnames = os.listdir(dir_name)
for suffix in suffixes:
fnames_suffix = [f for f in fnames if f.endswith(suffix)]
for fname in fnames_suffix:
print(f'{action} "{part}" into/from "{fname}"')
if action == 'remove' and fname.endswith(part+suffix):
new_name = fname[:-len(suffix) - len(part)] + suffix
print(f'fname is {fname}')
elif action == 'insert':
new_name = fname[:-len(suffix)] + part + suffix
else:
raise Exception(f'Unknown Action: {action}')
print(new_name)
old_file = os.path.join(dir_name, fname)
new_file = os.path.join(dir_name, new_name)
os.rename(old_file, new_file)
file_to_show = '/Users/ChrisHart/Downloads/test i love you daddy/'
subprocess.call(["open", "-R", file_to_show])
if __name__ == '__main__':
dir_name = '/Users/ChrisHart/Downloads/test i love you daddy/'
try:
change_fname(dir_name, part=' (z-lib.org)', action='remove')
except Exception as ex:
print(ex)
This is my program ^
file (part).pdf
file.pdf
The file will delete " (part)", so we get this
file.pdf
file.pdf
And they overwrite.
file.pdf
How can I fix this overwriting?

I also wrote a script that changes multiple files. Maybe my code helps you understand your problem:
import os
print(os.getcwd()) #Gives you your current directory
os.chdir('/PATH/TO/FILES') #Change directory to the files
for i in os.listdir('/PATH/TO/FILES'):
os.rename(i, i.replace('(z-lib.org)', ' ')) #replaces z-lib with one whitespace
print(i)
I know what you're trying to replace :D ... I did the same thing

Related

Modify .txt files, save originals and move modified

I modify many .txt files by adding string at the end of them.
How to save the original files and then move and rename modified ones?
I use os library.
i - iterated .txt files
new_name is variable consiting of random numbers
path=os.getcwd()
dirName=('new_directory')
This code only move files:
old_file = os.path.join(path, str(i))
new_path = os.path.join(path, dirName)
new_file = os.path.join(new_path, new_name)
os.rename(old_file, new_file)
I would like to use also os library to move and rename modified files.
Here is my whole code:
import os
import random
pressure=('Added pressure:')
dirName=('new_directory')
path=os.getcwd()
try:
os.mkdir(dirName)
print("Done: "+dirName)
except FileExistsError:
print("Directory" + dirName +" exist")
list=[]
for file in os.listdir("./"):
if file.endswith(".txt"):
lista.append(file)
for i in list:
f = open(i,"r")
file_contents = f.read()
print(f.read())
f.close()
if(pressure in file_contents):
print('It was added!')
else:
file=open(i, 'a')
rand_press=(str(random.randrange(980, 1040, 5))) #
rand_temp=(str(round(random.uniform(18, 26),2)))
press_and_temp=('Added pressure: \t'+rand_press+' mbar\n'+'Added temperature: \t'+rand_temp+' degC\n')
file.write(press_and_temp)
file.close()
new_name=str(rand_temp+'_'+rand_press+'.txt')
old_file = os.path.join(path, str(i))
new_path = os.path.join(path, dirName)
new_file = os.path.join(new_path, new_name)
os.rename(old_file, new_file)
Here are two suggestions.
1) Copy the file to a new location. Modify the second file. https://docs.python.org/3/library/shutil.html
2) Read the file, store it in some variable. Close the file. Create a new file in a new location, write to the file with your modifications, save it. https://www.guru99.com/reading-and-writing-files-in-python.html

Autoincrement file names

This issue comes from [here]. I tried asking about this is the link provided but I was downvoted and told to ask my own question...so here I am.
I tried replicating the results for my own project and it didn't work. when I try to save more than two files the script starts renaming each file instead of just the new ones I create:
file_1_2_2_1_4_4_6_2_2.pdf
file1_3_2_3_3-6_5_1.pdf
file2_1_1_1-7_3_9.pdf
etc
instead of
file_1.pdf
file_2.pdf
file_3.pdf
etc.
Any suggestions?
def save_file():
path = "/home/PycharmProjects/untitled/screening/"
newPath = "/home/PycharmProjects/untitled/screening/finished"
i = 1
for root, dirs, files in os.walk(path):
for name in files:
base, extension = os.path.splitext(name)
if not os.path.exists(os.path.join(newPath, base + extension)):
oldfile = os.path.join(os.path.abspath(root), name)
newfile = os.path.join(newPath, base + extension)
os.rename(oldfile, newfile)
else:
oldfile = os.path.join(os.path.abspath(root), name)
newfile = os.path.join(newPath, base + '_' + str(i) + extension)
i += 1
os.rename(oldfile, newfile)
Thank you in advance for you help!
The reason you get this behavior is that os.walk recurses into subdirs. Your target dir IS a subdir of your sourcedir - so you rename files from source to target and later os.walk into the target directory and rename some more into itself using the "renaming" strategy all the time because the file already exists.
Lenghty solution - most of it is creating file structures so this is a Minimal, Complete, and Verifiable example you can use.
See the documentation of topdown=False in os.walk
Create file structure
import os
files = [ f"file_{i:05}x.txt" for i in range(20)]
org = os.path.abspath("./dir1/dir2/")
new = os.path.abspath("./dir1/dir2/new/")
os.makedirs(new)
# create all in org
for f in files:
with open(os.path.join(org,f),"w") as f:
f.write(" ")
#create every 4th one in new
for f in files[::4]:
with open(os.path.join(new,f),"w") as f:
f.write(" ")
for root,dirs,files in os.walk(org):
print(root)
print(" [d] ", dirs)
print(" [f] ", sorted(files))
Output:
/tmp/dir1/dir2
[d] ['new']
[f] ['file_00000x.txt', 'file_00001x.txt', 'file_00002x.txt', 'file_00003x.txt',
'file_00004x.txt', 'file_00005x.txt', 'file_00006x.txt', 'file_00007x.txt',
'file_00008x.txt', 'file_00009x.txt', 'file_00010x.txt', 'file_00011x.txt',
'file_00012x.txt', 'file_00013x.txt', 'file_00014x.txt', 'file_00015x.txt',
'file_00016x.txt', 'file_00017x.txt', 'file_00018x.txt', 'file_00019x.txt']
/tmp/dir1/dir2/new
[d] []
[f] ['file_00000x.txt', 'file_00004x.txt', 'file_00008x.txt', 'file_00012x.txt',
'file_00016x.txt']
Fixed method
def save_file(old_path, new_path):
# topdown = False allows to modify the results to NOT recurse
for root, dirs, files in os.walk(old_path, topdown=False):
dirs = [] # do not recurse into subdirs ( whereto we copy the stuff )
root_abs = os.path.abspath(root)
new_abs = os.path.abspath(new_path)
for name in sorted(files): # sorting is convenience, not needed
old_file = os.path.join(root_abs, name)
new_file = os.path.join(new_abs, name)
# fix renaming logic (simplified) - looks until a unique name is found
i = 1
base, extension = os.path.splitext(name)
while os.path.exists(new_file):
# create a new name if it already exists
new_file = os.path.join(new_abs, f"{base}_{i}{extension}")
i += 1
# do the copy over
os.rename(old_file, new_file)
Usage:
# uses the org/new from above
# org = os.path.abspath("./dir1/dir2/")
# new = os.path.abspath("./dir1/dir2/new/")
save_file(org,new)
for root,dirs,files in os.walk(org):
print(root)
print(" [d] ", dirs)
print(" [f] ", sorted(files))
Output afterwards:
/tmp/dir1/dir2
[d] ['new']
[f] []
/tmp/dir1/dir2/new
[d] []
[f] ['file_00000x.txt', 'file_00000x_1.txt', 'file_00001x.txt', 'file_00002x.txt',
'file_00003x.txt', 'file_00004x.txt', 'file_00004x_1.txt', 'file_00005x.txt',
'file_00006x.txt', 'file_00007x.txt', 'file_00008x.txt', 'file_00008x_1.txt',
'file_00009x.txt', 'file_00010x.txt', 'file_00011x.txt', 'file_00012x.txt',
'file_00012x_1.txt', 'file_00013x.txt', 'file_00014x.txt', 'file_00015x.txt',
'file_00016x.txt', 'file_00016x_1.txt', 'file_00017x.txt', 'file_00018x.txt',
'file_00019x.txt']
You see some files in new got the _1 infix in it's name due to a same-named file was already in it.

I am simply trying to write a python script that will change the filename in a directory of files

I am trying to create a script in python 2.7 that will rename all the files in a directory. Below is the code I have so far. The first function removes any numbers in the file name. The second function is supposed to rename the new file name. I get the following error when the second function runs:
[Error 183] Cannot create a file when that file already exists
I know this is because I am not looping through the files and adding an incrementing number to the new filename, so the script changes the name of the first file, and then tries to change the name of the second file to the same name as the first, producing the error.
Can someone help me create a loop that adds an incrementing number to each filename in the directory?
I tried adding:
if file_name == filename:
file_name = file_name + 1
in the while loop, but that obviously doesn't work because I cant concatenate an integer with a string.
import os
def replace_num():
file_list = os.listdir(r"C:\Users\Admin\Desktop\Python Pics")
print(file_list)
saved_path = os.getcwd()
print("Current Working Directory is " + saved_path)
os.chdir(r"C:\Users\Admin\Desktop\Python Pics")
for file_name in file_list:
print("Old Name - " + file_name)
os.rename(file_name, file_name.translate(None, "0123456789"))
os.chdir(saved_path)
replace_num()
def rename_files():
file_list = os.listdir(r"C:\Users\Admin\Desktop\Python Pics")
print(file_list)
saved_path = os.getcwd()
print("Current Working Directory is " + saved_path)
os.chdir(r"C:\Users\Admin\Desktop\Python Pics")
for new_name in file_list:
print("New Name - " + new_name)
try:
os.rename(new_name, "iPhone")
except Exception, e:
print e
rename_files()
instead of doing:
if file_name == filename:
file_name = file_name + 1
do something like this:
counter = 0
for file_name in file_container:
if file_name == file_name: # this will always be True - so it's unnecessary
file_name = "{0}_{1}".format(file_name, counter)
counter += 1

Python: can't create subdirectory

I want to apply a test to list of files. The files that past the test should be moved to the directory "Pass"; the others should be moved to the directory "Fail".
Thus the output directory should contain subdirectories "Pass" and "Fail".
Here is my attempt:
if(<scan==pass>) # Working fine up to this point
dest_dir = outDir + '\\' + 'Pass' # The problem is here
print("Pass", xmlfile)
MoveFileToDirectory(inDir, xmlfile, dest_dir)
else:
dest_dir = os.path.dirname(outDir + '\\' + 'Fail')
print("Fail: ", xmlfile)
MoveFileToDirectory(inDir, xmlfile, dest_dir)
However, my code is moving the files to the output directory and not creating the "Pass" or "Fail" subdirectories. Any ideas why?
Use os.path.join(). Example:
os.path.join(outDir, 'Pass')
See this SO post
Also, we don't know what MoveFileToDirectory does. Use the standard os.rename:
os.rename("path/to/current/file.foo", "path/to/new/desination/for/file.foo")
See this SO post
So:
source_file = os.path.join(inDir, xmlfile)
if(conditionTrue):
dest_file = os.path.join(outDir, 'Pass', xmlfile)
print("Pass: ", xmlfile)
else:
dest_file = os.path.join(outDir, 'File', xmlfile)
print("Fail: ", xmlfile)
os.rename(source_file, dest_file)
Create directories exactly once:
import os
labels = 'Fail', 'Pass'
dirs = [os.path.join(out_dir, label) for label in labels]
for d in dirs:
try:
os.makedirs(d)
except EnvironmentError:
pass # ignore errors
Then you could move files into the created directories:
import shutil
print("%s: %s" % (labels[condition_true], xmlfile))
shutil.move(os.path.join(out_dir, xmlfile), dirs[condition_true])
The code exploits that False == 0 and True == 1 in Python.

Going into subfolders (python)

I've written something to remove special characters in Filenames. But it just includes the one folder and not it's subfolders. How can I do this also in subfolders and subsubfolders and so on?
import os
import re
def dir_list2(directory, *args):
fileList = []
content = os.listdir(directory)
for file in content :
dirfile = os.path.join(directory, file)
if os.path.isfile(dirfile):
if len(args) == 0:
fileList.append(dirfile)
else:
if os.path.splitext(dirfile)[1][1:] in args:
fileList.append(dirfile)
print "##################################################"
print "Old filename:", file
filename = file
remove = re.compile("[^.a-zA-z0-9_]")
output = remove.sub('_', filename)
newfile = directory + "/" + output
os.rename(dirfile, newfile)
print "Corrected filename:", output
#Removes Special Characters
return fileList
if __name__ == '__main__':
fileList = dir_list2('/path/')
Try using os.walk instead of os.listdir, it allows you to walk through a folder and its files and subfolders and so on.
Edit your code to be like:
content = os.walk(directory)
for dirpath, dirnames, filenames in content:
for file in filenames:
dirfile = os.path.join(dirpath, file)
# The rest of your code

Categories