I'm trying to rename my media file names based on the metadata.
File name format is song name - artist name
import os
from tinytag import TinyTag
import re
for root, dirs, files in os.walk("C:/Users/username/Desktop/Music/"):
for name in files:
tag = TinyTag.get(root + "\\" + name)
if tag.artist != "":
if name.endswith((".mp3",".m4a")):
# try:
file_ext = os.path.splitext(name)[-1]
old_name = os.path.join(root, name)
new_name = re.sub(' +', ' ', os.path.join(root, tag.title + " - " + tag.artist + file_ext))
print(new_name)
os.rename(old_name, new_name)
# except:
# pass
Every file works except for Little Red Corvette by Prince:
C:/Users/username/Desktop/Music/1973 - James Blunt.mp3
C:/Users/username/Desktop/Music/Little Red Corvette - Prince .mp3
Traceback (most recent call last):
File "C:/Users/username/PycharmProjects/Practice/editAudioFileNames.py", line 15, in <module>
os.rename(old_name, new_name)
ValueError: rename: embedded null character in dst
What does the ValueError mean? I noticed that there is an extra space after Corvette. I did use re.sub in my code to trim the file names.
Ignore the try, except for now because the code does work with it. I could change the file name manually since this is the only one out of 850 songs but I want to know for my future understanding.
As a side note, this is my first ever useful code! Optimization critiques are most welcome.
Can you please try replacing these lines
old_name = os.path.join(root, name)
new_name = re.sub(' +', ' ', os.path.join(root, tag.title + " - " + tag.artist + file_ext))
with these lines
old_name = os.path.join(root, name.strip())
new_name = re.sub(' +', ' ', os.path.join(root, tag.title.strip() + " - " + tag.artist.strip() + file_ext.strip()))
Thanks
Related
My code takes a list of PDF strings and combines creates PDFs by category. I am using PyPDF2 to combine and bookmark files. I am getting 'Unsupported PNG Filter 3' and 'Unsupported PNG Filter 4' when dealing with some files. I have found that if I manually open the file in Adobe and save over itself with the same name, the problem is corrected most of the time. Is there a way to do this programmatically? I can open the file but cannot figure out how to save and close it. Ideally this would run in the background.
def repair_file(self, path):
#Open PDF
subprocess.Popen([path], shell=True)
#Want a way to simply save like this
#subprocess.save([path], shell=True)
Alternatively, does anyone have a better solution for "repairing" files?
def repair_file(self, path):
#Open PDF
subprocess.Popen([path], shell=True)
#subprocess.write([path], shell=True)
#Tried
#with open(path, 'wb') as f:
# f.write(path)
#print('File Saved')
def combine_pdf(self, isos, pkg): #Unsupprted PNG Filter 4
#Combine PDFs
dir_name = r"E:\Test Folder\Y\Combined Isometrics"
suffix = ".pdf"
merger = PdfFileMerger(strict=False)
for iso in isos:
path = os.path.join(dir_name, iso + suffix)
print(pkg," : ",path)
bookmark = iso
try:
merger.append(open(path, 'rb'),bookmark)
except Exception as e:
#self.repair_file(pdf)
log = 'Error adding drawing: ' + str(pkg) + " : " + str(iso) + '\n' + '__Error: ' + str(e)
line = ",".join(str(iso)+str(pkg)+str(e))
stat = "Failed"
self.add_line(stat,line)
self.write2log(log)
try:
self.repair_file(path)
merger.append(open(path, 'rb'),bookmark)
except Exception as e:
#self.repair_file(pdf)
log = 'Error repairing: ' + str(pkg) + " : " + str(iso) + '\n' + '__Error: ' + str(e)
self.write2log(log)
try:
merger.write(pkg + ".pdf")
merger.close()
except Exception as e:
log = 'Error saving Package: ' + pkg + '\n' + '__Error: ' + str(e)
self.write2log(log)
EDIT
I know this is an old question, but I ran into a "filter" error as well. Using qpdf to copy all pages into a new file resolved it.
qpdf --empty --pages infile.pdf -- outfile.pdf
Using Python 3.8.3, I am trying to add a string to the end of my file names so they will be uniquely identified when combined into a large directory. In this case, I am trying to add a simple _a to the end of the file name, but before the suffix.
For example, all of my files (workplace directory contains JPG and TXT files) need to go from a file name of P025525_002.jpg to P025525_002_a.jpg and the same for TXT files.
However, I get the following error:
Traceback (most recent call last):
File "add_name.py", line 12, in <module>
new_name = '{1} {2} {3}'.format(f_name + str('_a'), f_ext)
IndexError: Replacement index 2 out of range for positional args tuple
Here's the script I have written:
import os
os.chdir('E:\\Users\\rest_of\\file_path')
def increment():
global COUNT
COUNT = COUNT + 1
for f in os.listdir(os.getcwd()):
f_name, f_ext = os.path.splitext(f)
new_name = '{1} {2} {3}'.format(f_name + str('_a'), f_ext)
os.rename(f, new_name)
Just change new_name to :
new_name = f'{f_name}_a{f_ext}'
You problem with your .format() is you specified three place holders, but you passed 2 values. Also note that you should count from 0 not 1, 3 is out of range:
new_name = '{0}_a{1}'.format(f_name, f_ext).
btw in your case you could skip numbers and use bare {}.
I recommend f-string though.
Change this line -
for f in os.listdir(os.getcwd()):
f_name, f_ext = os.path.splitext(f)
new_name = '{1} {2} {3}'.format(f_name + str('_a'), f_ext)
os.rename(f, new_name)
to -
for f in os.listdir(os.getcwd()):
f_name, f_ext = os.path.splitext(f)
new_name = '{0} {1}'.format(f_name + str('_a'), f_ext)
os.rename(f, new_name)
Or use f-strings which is more readable -
new_name = f'{f_name}_a{f_ext}'
This worked for me!
for f in os.listdir(os.getcwd()):
f_name, f_ext = os.path.splitext(f)
new_name = '{2} {3}'.format(f_name + str('_a'), f_ext)
os.rename(f, new_name)
+ between 2 strings is used for string concatenation. So the strings are actually combined to one single string. So in theory, there are 2 arguments but you have given to pass 3 arguments. That is the problem
I have the a similar folder structure for which I need to pull the latest .jpg from each subdirectory:
+ C:\\myfiles
+ parentdir1
+ subdir1
+ somename1.jpg
+ somename2.jpg
+ ...
+ subdir2
+ somename3.jpg
+ somename4.jpg
+ ...
+ ...
+ parentdir2
+ subdir1
+ somename5.jpg
+ somename6.jpg
+ ...
+ subdir2
+ somename7.jpg
+ somename8.jpg
+ ...
+ ...
+ parentdir3
+ subdir1
+ somename9.jpg
+ somename10.jpg
+ ...
+ subdir2
+ somename11.jpg
+ somename12.jpg
+ ...
+ ...
+ ...
I don't know any of the names of the folders or files but I need to access the last 2 .jpg files in each subdir.
For the sake of making this simple, let's just assume I need to print the last 2 files created in the subdir.
I wrote a script that will search all subdir's in a given parentdir, but I actually need to go iterate through all parentdir's as well
import os
path = 'C:\\myfiles'
filelist = []
for i in range(len(os.listdir(path))):
subpath = path + '\\' + os.listdir(path)[i]
for root, dirs, files in os.walk(subpath):
for file in os.listdir(subpath):
filelist.append(os.path.join(root, file))
sorted_filelist = sorted(filelist, key=os.path.getctime)
print('the latest jpg file in ' + root + ' is: ' + sorted_filelist[-1])
print('the 2nd last jpg file in ' + root + ' is: ' + sorted_filelist[-2])
filelist.clear()
I think this will do what you want. Note that I sort the files by their last modification times, rather than their creation time because I think that's the way to determine which are "most recent".
import glob
import os
N_MOST_RECENT = 2
path = 'C:\\myfiles'
for entry in os.listdir(path):
subpath = os.path.join(path, entry)
if os.path.isdir(subpath):
for subentry in os.listdir(subpath):
subentrypath = os.path.abspath(os.path.join(subpath, subentry))
if os.path.isdir(subentrypath):
jpg_files = glob.iglob(os.path.join(subentrypath, '*.jpg'))
sorted_filenames = sorted(jpg_files, key=os.path.getmtime)
# Create list of filenames of the N most recent files.
most_recent = [os.path.split(name)[-1] # Extract filename from path.
for name in sorted_filenames[-N_MOST_RECENT:]]
print(f'{N_MOST_RECENT} most recent .jpg files in "{subentrypath}":\n'
f' {most_recent}')
Try iterating through the parent directory, and then through all the sub-directories, using os.listdir().
import os
parent_dir = 'path/to/parent/dir'
for subdir in os.listdir(parent_dir):
if not os.path.isdir(subdir):
continue
sorted_filelist = sorted(
[os.path.join(parent_dir, subdir, f) for f in os.listdir(subdir)
if os.path.splitext(f)[1] == '.jpg'],
key=os.path.getctime, reverse=True)
print(sorted_filelist[:2])
The following code works as intended to create a new file (or files) using the file name (or names) in the directory. However it also creates a file with a tilde in the title and a duplicate of the word2find. Here is an example result
~$17 Q3 Xcel retire retire.txt
I don't understand why this is happening. Any explanations will be appreciated. Cheers, BobS
import os, os.path,re, pprint,sys, nltk
sourcedir = 'C:/Users/Public/EnvDef/Proj/1 ErnCls/2 IOUErnClsQrtr/2017 Q3/23a Xcel'
os.chdir (sourcedir)
cwd = os.getcwd()
print ('New Current Working Directory %s' % cwd)
for dirPath, subdirNames, fileList in os.walk(cwd):
for filename in fileList:
with open (filename,'r', encoding="ascii", errors ="surrogateescape") as fin:
FileinA=(fin.read())
print (' ')
#create basename by deleting the file name suffix
basename=os.path.splitext(filename)[0]
print (basename)
#tokenize file
FileinB=nltk.sent_tokenize(FileinA)
word2find = 'retire'
result = [sentence for sentence in FileinB if word2find in sentence]
with open (basename+' '+ word2find +'.txt', 'w', encoding="ascii", errors="surrogateescape") as filetowrite:
filetowrite.write(basename+ ' Retire' + "\n" +"\n")
for line in result:
filetowrite.write(line + "\n")
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.