os.rename deleting files python 3 - python

Python novice, my simple script gets a given directory and renames all files sequentially, however it is deleting the files but the print is showing the files names getting renamed, not sure where its going wrong here.
Also, in what order does it retrieve these files?
import os
path = os.path.abspath("D:\Desktop\gp")
i = 0
for file_name in os.listdir(path):
try:
print (file_name + " - " + str(i))
os.rename(os.path.join(path,file_name), str(i))
except WindowsError:
os.remove(str(i))
os.rename(os.path.join(path,file_name), str(i))
i += 1
print(str(i) + " files.")
Edit
Below is the solution with working code, retrieves all files in a dir by creation date and assigns them a iterated number while retaining file extension.
import os
def sorted_dir(folder):
def getctime(name):
path = os.path.join(folder, name)
return os.path.getctime(path)
return sorted(os.listdir(path), key=getctime)
path = os.path.abspath("D:\Path\Here")
i = 0
for file_name in sorted_dir(path):
_, ext = os.path.splitext(file_name)
print (file_name + " - " + str(i)+ext)
os.rename(os.path.join(path,file_name), os.path.join(path, str(i) + ext))
i += 1
print(str(i-1) + " files.")

The problem is that you're using an absolute path for the source, but a relative path for the destination. So the files aren't getting deleted, they're just getting moved into the current working directory.
To fix it so they get renamed into the same directory they were already in, you can do the same thing on the destination you do on the source:
os.rename(os.path.join(path,file_name), os.path.join(path, str(i)))
From a comment, it sounds like you may want to preserve the extensions on these files. To do that:
_, ext = os.path.splitext(file_name)
os.rename(os.path.join(path,file_name), os.path.join(path, str(i) + ext))

Related

Losing absolute paths after returning them from function

I have this function here that renames (if necessary) all files in a given folder and returns all filenames as absolute paths:
I forgot to mention: filepath is always an absolute path.
import re
import os
# This function renames all files in a given
# folder and return them as absolute paths
def rename_get_Files(filepath):
files = os.listdir(filepath)
files_list = []
counter = 1
files_renamed = 0
for filename in files:
# If the file does not start with 'Offer_Pic_' > rename it and add to the files_list
if not re.search('Offer_Pic_.+', filename):
file_name, file_extension = os.path.splitext(filepath+filename)
print(file_extension)
new_filename = "Offer_Pic_" + str(counter) + file_extension
old_filename = filepath + filename
new_filename = filepath + new_filename
# rename() function will
# rename all the files
os.rename(old_filename, new_filename)
counter += 1
print(f'This is the new filename: ' + new_filename)
files_list.append(new_filename)
files_renamed += 1
else:
# Append the absolute paths of all already correctly named files to the files_list
files_list.append(os.path.abspath(filename))
print(files_list)
print(f'We have renamed ' + str(files_renamed) + ' files.')
return files_list
However, when I call the function from another one to use these absolute paths:
pictures = rename_get_Files(filepath)
print(pictures)
... it returns the paths being inside the script's working directory.
Because of that, the next function of my script crashes because it assumes that the files are in the working directory of the script - which they are not as they were not moved from their initial location (filepath).
Please help me to keep the absolute file paths.
I tried to regain the absolute path of the pictures, but the wrong one (inside script dir keeps being returned)
for pic in pictures:
abs_path_pic = os.path.abspath(pic)
print(pic)
print(abs_path_pic)
pictureBox.send_keys(abs_path_pic)
I found the error: initially no absolute path was returned by os.
I added to the end of the function:
path = os.path.abspath(filepath)
files_list = [entry.path for entry in os.scandir(path) if entry.is_file()]
The whole function now looks like this:
# This function renames all files in a given folder and return them as absolute paths
def rename_get_files(filepath):
print(f'this is the given filepath: {filepath}')
files = os.listdir(filepath)
files_list = []
print(f'these are our initial files: {files}')
counter = 1
files_renamed = 0
for filename in files:
# If the file does not start with 'Offer_Pic_' > rename it and add to the files_list
if not re.search('Offer_Pic_.+', filename):
file_name, file_extension = os.path.splitext(filepath+filename)
print(file_extension)
new_filename = "Offer_Pic_" + str(counter) + file_extension
old_filename = filepath + "/" + filename
print(old_filename)
new_filename = filepath + "/" + new_filename
print(new_filename)
# rename() function will
# rename all the files
os.rename(old_filename, new_filename)
counter += 1
print(f'This is the new filename: ' + new_filename)
files_list.append(os.path.abspath(new_filename))
files_renamed += 1
else:
# Append the absolute paths of all already correctly named files to the files_list
files_list.append(os.path.abspath(filename))
print(f'We have renamed ' + str(files_renamed) + ' files.')
path = os.path.abspath(filepath)
files_list = [entry.path for entry in os.scandir(path) if entry.is_file()]
print(f'this is our files_list, no files were renamed: {files_list}')
return files_list
Now it works perfectly! Thank you all for your help!

Sorting corresponding files into the same directory

I've got 6 directories (A, B, C, D, E, F) containing .mov files.
The structure is:
A
-0001_01.mov
-0002_01.mov
-...
B
-0001_02.mov
-0002_02.mov
-...
And so on.
First, I want to create as many directories as there are files in one of the directories mentioned above.
Let's say A contains 35 .mov files (B, C .. contain the same amount of .mov files).
I now got 35 folders starting from "01" up to "35".
Now I want to copy each corresponding .mov file into the same directory, which means 0001_01.mov - 0001_06.mov go into "01", 0002_01.mov - 0002_06.mov go into "02" and so on.
I've got the creation of the directories working, but I just can't wrap my head around the copying part.
import os
pathA = ("./A/")
pathB = ("./B/")
pathC = ("./C/")
pathD = ("./D/")
pathE = ("./E/")
pathF = ("./F/")
path, dirs, filesA = next(os.walk(pathA))
file_countA = len(filesA)
path, dirs, filesB = next(os.walk(pathB))
file_countB = len(filesB)
path, dirs, filesC = next(os.walk(pathC))
file_countC = len(filesC)
path, dirs, filesD = next(os.walk(pathD))
file_countD = len(filesD)
path, dirs, filesE = next(os.walk(pathE))
file_countE = len(filesE)
path, dirs, filesF = next(os.walk(pathF))
file_countF = len(filesF)
path2 = ("./")
if file_countA == file_countB == file_countC == file_countD == file_countE == file_countF:
print("true")
else:
print ("false")
for i in range(file_countA):
try:
if i < 9:
os.mkdir(path2 + "0" + str(i + 1))
path3 = ("./" + "0" + str(i + 1))
print (path3)
elif i >= 9:
os.mkdir(path2 + str(i + 1))
path3 = ("./" + str(i + 1))
print (path3)
except OSError:
print ("Creation of the directory %s failed" % path2)
else:
print ("Successfully created the directory %s " % path2)
This is my first time using python, I think the code reflects that.
I've now wasted countless hours on this, so any help is appreciated.
So I changed your code quite a bit and tested it quickly on my system and it seemed to do what you wanted. Can you try and let me know if this gave you idea of how it can be done?
Disclaimer: I'm not Python expert by any means but I find my way around it and this is most likely not the prettiest solution but it deos work on my machine exactly as you wanted it. Just make sure you run it from inside your folder and if you are not running it from outside your folder then change cwd = os.getcwd() to cwd = "path-to-your-folder"
import os
import shutil
import glob
paths = ["/A/","/B/","/C/","/D/","/E/","/F/"]
cwd = os.getcwd()
num_folders = 0
for path in paths:
num_files = len([f for f in os.listdir(cwd+path)if os.path.isfile(os.path.join(cwd+path, f))])
if num_files>num_folders:
num_folders = num_files
for i in range(num_folders):
try:
if i < 9:
fname = cwd + "/0" + str(i + 1)
os.mkdir(fname)
for path in paths:
source = cwd + "/" + path
filename = "000{}_*.mov".format(i+1)
for file in glob.glob(os.path.join(source,filename)):
shutil.copy2(file,fname)
elif i >= 9:
fname = cwd + "/" + str(i + 1)
os.mkdir(fname)
for path in paths:
source = cwd + "/" + path
filename = "00{}_*.mov".format(i+1)
for file in glob.glob(os.path.join(source,filename)):
shutil.copy2(file,fname)
except OSError:
pass
I'm no python expert either (look at my scores too, hi), but I've tried to keep your original coding order as much as possible. I would recommend to look at different codes for real expert-tier code but it seems to do what you're asking for :
import os
import shutil
mov_pathes = ["./a/", "./b/"]
all_files = []
lengths = []
for mov_path in mov_pathes :
# listdir gives you all files in the direcetory
files_in_dir = os.listdir(mov_path)
# we'll save those in a list along with where it's from ,
# ex : ('./patha/',['0001_01.mov','0002_01.mov'])
all_files.append((mov_path, files_in_dir))
# also length info for "all items are equal length" comparison in the future
lengths.append(len(files_in_dir))
if lengths.count(lengths[0]) == len(lengths) :
print ("true")
else :
print ("false")
base_dir = "./"
for i in range (1,lengths[0]+1) :
try :
# zfill(n) fills rest of your string to 0, (ex. "7".zfill(5) gives you 00007), probably helpful for future
path_name = base_dir + str(i).zfill(2)
os.mkdir(path_name)
except OSError :
print ("Creation of the directory {path_name} failed".format(path_name = path_name))
else :
print ("Successfully created the directory {path_name}".format(path_name = path_name))
Does exactly the same thing but it would probably make maintaining your code easier laster on.
for your real question, IF we're sure that your inputs are gonna look like 00XX_NN.mov, adding
for files in all_files :
# Remember we saved as (original dir, list of files in the dir?)
# This is a original dir
source_dir = files[0]
# This is list of files in that directory
source_files = files[1]
for file in source_files :
# so original file is located in source_dir + file
source_file = source_dir + file
# and your target directory is 00XX, so getting file[2:4] gives the target directory
target_dir = base_dir + file[2:4]
#shutil.copy (source file, target directory) copies your files.
shutil.copy (source_file , target_dir)
seems to do what you're asking for, at least for me. Once again I'm no expert so let me know if it's not working!
tested with :
./a
- 0001_01
- 0002_01
- 0003_01
./b
- 0001_02
- 0002_02
- 0003_02
result :
./01 :
- 0001_01
- 0001_02
./02 :
- 0002_01
- 0002_02
./03 :
- 0003_01
- 0003_02

Batch rename files in Python 2.7

I'm trying to rename files in a directory so that it the new name is the original name followed by a space + "17-" + an incrementally increasing number.
The code below is just renaming files from 151, upward. How do I keep the original name, adding the text "17-" and the numbers?
import os
path = 'C:\Users\dcs\Desktop\Test direct'
files = os.listdir(path)
i = 151
for file in files:
os.rename(os.path.join(path, file), os.path.join(path, str(i)+'.TIF'))
i = i+1
Simply by writing that concatenation expression. If I understand your details correctly, your new loop body would be
new_name = file + " 17-" + str(i) + ".TIF"
os.rename(os.path.join(path, file),
os.path.join(path, new_name) )
i += 1
This would change file "ABC" into file "ABC 17-151.TIF"; the next would contain "17-152", and so on.
FACEPALM
file is a built-in type. Change the loop index.
for fname in files:
new_name = fname + " 17-" + str(i) + ".TIF"
os.rename(os.path.join(path, fname), new_name)
i += 1
If I understand Prune's suggestion above, which I obviously don't, it would look like:
import os
path = 'C:\Users\dcs\Desktop\Test direct'
files = os.listdir(path)
i = 151
#The part that I want to strip the extensions from
for file in files:
new_name = file[:-3]
#The part that words correctly (thanks Prune)
for fname in files:
new_name = fname + " 17-" + str(i) + ".TIF"
os.rename(os.path.join(path, fname), new_name)
i += 1
However the first part, meant to strip the file of it's extension isn't working.

Unzipping, renaming and migrating contents of GDB directory - Python

Currently trying to develop a catch all script that when pointed to a folder it will look through all of the subfolders and anything that is a .gdb will be moved to a new folder. Some GDBS are zipped and have a folder which then contains the GDB inside. If the GDB files have the same name once extracted, they will be appended with the suffix _2, _3, _4 and then moved to the folder with the other GDBs and won't conflict with any filenames.
Everything works except the renaming. Whereby it will rename one ok and then start placing folders inside of another gdb, before eventually failing with. WindowsError: [Error 183] Cannot create a file when that file already exists.
import shutil, errno, re, os, zipfile, os.path, sys
def unzip(source_filename, dest_dir):
with zipfile.ZipFile(source_filename) as zf:
for member in zf.infolist():
words = member.filename.split('/')
path = dest_dir
for word in words[:-1]:
drive, word = os.path.splitdrive(word)
head, word = os.path.split(word)
if word in (os.curdir, os.pardir, ''): continue
path = os.path.join(path, word)
zf.extract(member, path)
results = []
input_path = sys.argv[1]
output_path = sys.argv[2]
if input_path not in output_path:
for path, subdirs, files in os.walk(input_path):
for f in files:
if f.endswith(".zip") or f.endswith(".ZIP"):
unzip(os.path.join(path,f), path)
if input_path not in output_path:
for path, subdirs, files in os.walk(input_path):
counter = 2
for dir_name in subdirs:
if os.path.join(path, dir_name).endswith(".gdb") or os.path.join(path, dir_name).endswith(".GDB"):
if os.path.exists(output_path + "\\" + dir_name):
print "Moving " + os.path.join(path, dir_name) + " To " + output_path + "\\" + str(counter) + dir_name
os.rename(os.path.join(path, dir_name), output_path + "\\" + dir_name[:-4] + "_" + str(counter) + ".gdb")
counter + 1
else:
print "Moving " + os.path.join(path, dir_name) + " To " + output_path
shutil.move(os.path.join(path, dir_name), output_path)
else:
print "########################################"
print "########################################"
print "Please select a different output path"
print "The output path should not be contained"
print " In the input path"
print "########################################"
print "########################################"
Any help anyone could give would be greatly appreciated. Cheers!

python function not repeating

I have a python tool to 'touch' (utime) a file, then move to another folder. However, if the file already exists in the destination folder, it is silently overwritten. I would like to check for a file of the same name in the destination folder and, if it exists, rename the one I am moving to its name plus '-n' at the end, where n is a number starting at '1' and, if the file with '-1' at the end already exists, '-2' etc.
For example, say in the source folder is a file 'foo.txt', but there is one 'foo.txt' in the destination folder as well. This function should return '(absolute path)/foo-1.txt'.
So, I have made a function to check for these circumstances and return the modified string, so I can use rename later and not overwrite. However, currently, if the file exists, it returns nothing. Following is the function code, assuming these vars:
fileName - input filepath, absolute path. e.g. /Users/foo/sourceFolder/bar.txt
index - iterator variable, set to '1' at the start of each file being opened (externally to function)
def checkExists(fileName):
global index
print "checkExists(" + fileName + ")"
if exists(fileName):
splitPath = split(newFile)
splitName = splitext(splitPath[1])
newSplitName = splitName[0] + "-" + str(index)
index += 1
newName = splitPath[0] + "/" + newSplitName + splitName[1]
print "newName = " + newName
else:
print "(else) fileName = " + fileName
print "(else) fileName = " + str(type(fileName))
print ""
return fileName
checkExists(newName)
Now it seems that the inner call for checkExists() at the end is not running.
I hope I have been clear in my explanation.
IAmThePiGuy
P.S. I do not want to hear about potential race problems with utime, I know that the files in the source directory will not be accessed by anything else.
Your problem is that, if the file exists, you don't return anything. I think you're intending to use recursion to check the new filename, but you don't return the result of that call. Here's a stab:
def checkExists(fileName, index=0):
print "checkExists(" + fileName + ")"
if exists(fileName):
splitPath = split(newFile)
splitName = splitext(splitPath[1])
newSplitName = splitName[0] + "-" + str(index)
index += 1
newName = splitPath[0] + "/" + newSplitName + splitName[1]
print "newName = " + newName
return checkExists(newName, index) # recurse
else:
print "(else) fileName = " + fileName
print "(else) fileName = " + str(type(fileName))
print ""
return fileName
I also took the liberty of moving the recursive call closer to the generation of newName and removing the global variable and replacing that with recursion as well.
Here's an iterative approach to a similar problem:
def copyfile(path, dstdir, verbose=True, dryrun=False):
"""Copy `path` file to `dstdir` directory incrementing name if necessary."""
filename = os.path.basename(path)
basename, ext = os.path.splitext(filename)
for i in itertools.count(2):
destpath = os.path.join(dstdir, filename)
if not os.path.exists(destpath):
if verbose:
print(path, '->', destpath)
if not dryrun:
shutil.copyfile(path, destpath)
return
# increment filename
filename = "%s_%02d%s" % (basename, i, ext)

Categories

Resources