Bulk rename txt files with different parts using Python - python

I have a list of files that I wish to rename to.
Receipt ABC-001 623572349-1.txt --> Receipt ABC-001A.txt
Receipt ABC-001 623572349-2.txt --> Receipt ABC-001B.txt
However, even at the first step, everytime I get the following error "Cannot create a file when that file already exists:". What would be the best option to achieve the above outcome where files ending with 1 will become A; ending with 5.txt will become E.txt, and soforth?
Below is the code I have used:
import os, fnmatch
#Set directory of locataion; include double slash for each subfolder.
file_path = "C:\\Users\\Mr.Slowbro\\Desktop\\TBU\\"
#Set file extension accordingly
files_to_rename = fnmatch.filter(os.listdir(file_path), '*.txt')
for file_name in files_to_rename:
file_name_new = file_name[-5:5]
os.rename(file_path + file_name, file_path + file_name_new)

This should help you out. Using the ord() function returns the Unicode point of a character. So 'a' would be 97, 'b' would be 98, etc. Likewise, chr() returns the character of that Unicode point. So, I think the code below will help you with your issue.
#Set directory of locataion; include double slash for each subfolder.
file_path = "C:\\Users\\Mr.Slowbro\\Desktop\\TBU\\"
#Set file extension accordingly
files_to_rename = fnmatch.filter(os.listdir(file_path), '*.txt')
for file_name in files_to_rename:
number = chr(int(file_name[-5]) - 1 + ord('A'))
file_name_new = 'Receipt ABC-001' + number + '.txt'
os.rename(file_name, file_name_new)```

Related

How to set a single "\" in a filename (I've tried all the ways I could find}

I have a script that should rename the file default.xex to the value of FileName[:-1] which is the name of the directory the xex file is in. The code I have is:
`
# This renames default.xex to the correct FileName.xex
for filename in DirectoryList:
path = HomePath + UnpackedPath + FileName + FileName + FileName + FileName
filename = FileName[:-1] + "\\default.xex"
src = filename
dst = FileName[:-1] + ".xex"
os.rename(os.path.join(path, src), os.path.join(path, dst))
`
however this always throws an error showing \FileName.xex when \FileName.xex is expected.
The error is:
Exception has occurred: FileNotFoundError
[Errno 2] No such file or directory: '/home/corey/XBLA_Unpacked/FarCry 3 Blood Dragon/FarCry 3 Blood Dragon/FarCry 3 Blood Dragon/FarCry 3 Blood Dragon/FarCry 3 Blood Dragon\default.xex' -> '/home/corey/XBLA_Unpacked/FarCry 3 Blood Dragon/FarCry 3 Blood Dragon/FarCry 3 Blood Dragon/FarCry 3 Blood Dragon/FarCry 3 Blood Dragon.xex'
This renames default.xex to the correct FileName.xex
for filename in DirectoryList:
path = HomePath + UnpackedPath + FileName + FileName + FileName + FileName
filename = FileName[:-1] + "\\default.xex"
src = filename
dst = FileName[:-1] + ".xex"
os.rename(os.path.join(path, src), os.path.join(path, dst))
Edit: I just realized this only shows 1 , however on my screen in VS Code and in this text editor it shows 2
the original xex file is FarCry 3 Blood Dragon\default.xex.
I have tried every solution I could find while googling and looking at other people's solutions on here and nothing seems to work. I tried setting it as a specific string variable and running it that way and it still resulted in \.
The error message is showing the repr of the string, in order to be unambiguous if there are any "strange" characters in there. There is only one backslash in the string, but just as it has to be doubled when it occurs in a string literal, it will be doubled in the output, because a single backslash would be used for special characters.
For example, if I run the following program
import os
f='a\\b'
print(len(f))
os.rename(f, 'foo')
it prints 3, showing that the string is just 3 characters, but then it gives the error message
FileNotFoundError: [Errno 2] No such file or directory: 'a\\b' -> 'foo'

python regex: Parsing file name

I have a text file (filenames.txt) that contains the file name with its file extension.
filename.txt
[AW] One Piece - 629 [1080P][Dub].mkv
EP.585.1080p.mp4
EP609.m4v
EP 610.m4v
One Piece 0696 A Tearful Reunion! Rebecca and Kyros!.mp4
One_Piece_0745_Sons'_Cups!.mp4
One Piece - 591 (1080P Funi Web-Dl -Ks-)-1.m4v
One Piece - 621 1080P.mkv
One_Piece_S10E577_Zs_Ambition_A_Great_and_Desperate_Escape_Plan.mp4
these are the example filename and its extension. I need to rename filename with the episode number (without changing its extension).
Example:
Input:
``````
EP609.m4v
EP 610.m4v
EP.585.1080p.mp4
One Piece - 621 1080P.mkv
[AW] One Piece - 629 [1080P][Dub].mkv
One_Piece_0745_Sons'_Cups!.mp4
One Piece 0696 A Tearful Reunion! Rebecca and Kyros!.mp4
One Piece - 591 (1080P Funi Web-Dl -Ks-)-1.m4v
One_Piece_S10E577_Zs_Ambition_A_Great_and_Desperate_Escape_Plan.mp4
Expected Output:
````````````````
609.m4v
610.m4v
585.mp4
621.mkv
629.mkv
745.mp4 (or) 0745.mp4
696.mp4 (or) 0696.mp4
591.m4v
577.mp4
Hope someone will help me parse and rename these filenames. Thanks in advance!!!
As you tagged python, I guess you are willing to use python.
(Edit: I've realized a loop in my original code is unnecessary.)
import re
with open('filename.txt', 'r') as f:
files = f.read().splitlines() # read filenames
# assume: an episode comprises of 3 digits possibly preceded by 0
p = re.compile(r'0?(\d{3})')
for file in files:
if m := p.search(file):
print(m.group(1) + '.' + file.split('.')[-1])
else:
print(file)
This will output
609.m4v
610.m4v
585.mp4
621.mkv
629.mkv
745.mp4
696.mp4
591.m4v
577.mp4
Basically, it searches for the first 3-digit number, possibly preceded by 0.
I strongly advise you to check the output; in particular, you would want to run sort OUTPUTFILENAME | uniq -d to see whether there are duplicate target names.
(Original answer:)
p = re.compile(r'\d{3,4}')
for file in files:
for m in p.finditer(file):
ep = m.group(0)
if int(ep) < 1000:
print(ep.lstrip('0') + '.' + file.split('.')[-1])
break # go to next file if ep found (avoid the else clause)
else: # if ep not found, just print the filename as is
print(file)
Program to parse episode number and renaming it.
Modules used:
re - To parse File Name
os - To rename File Name
full/path/to/folder - is the path to the folder where your file lives
import re
import os
for file in os.listdir(path="full/path/to/folder/"):
# searches for the first 3 or 4 digit number less than 1000 for each line.
for match_obj in re.finditer(r'\d{3,4}', file):
episode = match_obj.group(0)
if int(episode) < 1000:
new_filename = episode.lstrip('0') + '.' + file.split('.')[-1]
old_name = "full/path/to/folder/" + file
new_name = "full/path/to/folder/" + new_filename
os.rename(old_name, new_name)
# go to next file if ep found (avoid the else clause)
break
else:
# if episode not found, just leave the filename as it is
pass

fnmatch working inconsistently in different scripts

I am working on a python script that will write input files for an analysis program I use. One of the steps is to take a list of filenames and search the input directory for them, open them, and get some information out of them. I wrote the following using os.walk and fnmatch in a test-script that has the directory of interest hard-coded in, and it worked just fine:
for locus in loci_select: # for each locus we'll include
print("Finding file " + locus)
for root, dirnames, filenames in os.walk('../phylip_wigeon_mid1_names'):
for filename in fnmatch.filter(filenames, locus): # look in the input directory
print("Found file for locus " + locus + " in set")
loci_file = open(os.path.join('../phylip_wigeon_mid1_names/', filename))
with loci_file as f:
for i, l in enumerate(f):
pass
count = (i) * 0.5 # how many individuals present
print(filename + "has sequences for " + str(count) + " individuals")
...and so on (the other bits all work, so I'll spare you).
As soon as I put this into the larger script and switch out the directory names for input arguments, though, it seems to stop working between the third and fourth lines, despite being nearly identical:
for locus in use_loci: # for each locus we'll include
log.info("Finding file " + locus)
for root, dirnames, filenames in os.walk(args.input_dir):
for filename in fnmatch.filter(filenames, locus): # look in the input directory
log.info("Found file for locus " + locus + " in set")
loci_file = open(os.path.join(args.input_dir, filename))
with loci_file as f:
for i, l in enumerate(f):
pass
count = (i) * 0.5 # how many individuals present
log.info(filename + "has sequences for " + str(count) + " individuals")
I've tested it with temporary print statements between the suspected lines, and it seems like they are the culprits, since my screen output looks like:
2015-11-17 15:53:20,505 - write_ima2p_input_file - INFO - Getting selected loci for analysis
2015-11-17 15:53:20,505 - write_ima2p_input_file - INFO - Finding file uce-7999_wigeon_mid1_contigs.phy
2015-11-17 15:53:20,629 - write_ima2p_input_file - INFO - Finding file uce-4686_wigeon_mid1_contigs.phy
2015-11-17 15:53:20,647 - write_ima2p_input_file - INFO - Finding file uce-5012_wigeon_mid1_contigs.phy
...and so on.
I've tried switching out to glob, as well as simple things like rearranging where this section falls in my larger code, but nothing is working. Any insight would be much appreciated!

How to list files in directory and subdirectory based on filesize greater than 10kb using python

I have gone through following scenarios
which we can list files in a directory
Which we can list files with their file sizes
But now I need to list only the files just they are greater than some X KB with the input given by the user.
Please help with some suitable examples
Here is my code
import os
for path, dirs, files in os.walk("PathToDir" ):
for f in files:
size=os.path.getsize( os.path.join( path, f )
print path, f, size
Here's an example of how to go 'walk' through the files in a directory, and then printing out the ones that meet a file size criterion:
Note: How to 'walk' was found here:
concatenate the directory and file name
# Task: List only files that are greater than some X KB with the input given by the user.
import os
# The directory that we are interested in
myPath = "/users/george/documents/"
# The min size of the file in Bytes
mySize = '10000'
# All the file paths will be stored in this list
filesList= []
for path, subdirs, files in os.walk(myPath):
for name in files:
filesList.append(os.path.join(path, name))
for i in filesList:
# Getting the size in a variable
fileSize = os.path.getsize(str(i))
# Print the files that meet the condition
if int(fileSize) >= int(mySize):
print "The File: " + str(i) + " is: " + str(fileSize) + " Bytes"
I achieved it using the pathlib module. I am running Python 3.7.6 on Windows.
Here's the code:
import os
from pathlib import Path
dir_path = Path('//?/D:/TEST_DIRECTORY')
# IMP_NOTE: If the path is 265 characters long, which exceeds the classic MAX_PATH - 1 (259) character
# limit for DOS paths. Use an extended (verbatim) path such as "\\\\?\\C:\\" in order
# to access the full length that's supported by the filesystem -- about 32,760 characters.
# Alternatively, use Windows 10 with Python 3.6+ and enable long DOS paths in the registry.
# pathlib normalizes Windows paths to use backslash, so we can use
# Path('//?/D:/') without having to worry about escaping backslashes.
F_LIST = list(x for x in dir_path.rglob('*.*') if x.is_file() and os.path.getsize(x) >= 10000)
for f in F_LIST:
print(f.parts[-1] + " ===> " + "Size = " + str(format(os.path.getsize(f), ',d')) + "\n")
# path.parts ==> Provides a tuple giving access to the path’s various components
# (Ref.: pathlib documentation)
Hope this helps! :-)
limit = raw_input('Enter a file size: ')
if int(limit) > 0:
import os
for path, dirs, files in os.walk("PathToDir" ):
for f in files:
size=os.path.getsize( os.path.join( path, f )
if size > limit :
print path, f, size

Automator/Applescript rename files if

I have a large list of images that have been misnamed by my artist. I was hoping to avoid giving him more work by using Automator but I'm new to it. Right now they're named in order what001a and what002a but that should be what001a and what001b. So basically odd numbered are A and even numbered at B. So i need a script that changes the even numbered to B images and renumbers them all to the proper sequential numbering. How would I go about writing that script?
A small Ruby script embedded in an AppleScript provides a very comfortable solution, allowing you to select the files to rename right in Finder and displaying an informative success or error message.
The algorithm renames files as follows:
number = first 3 digits in filename # e.g. "006"
letter = the letter following those digits # e.g. "a"
if number is even, change letter to its successor # e.g. "b"
number = (number + 1)/2 # 5 or 6 => 3
replace number and letter in filename
And here it is:
-- ask for files
set filesToRename to choose file with prompt "Select the files to rename" with multiple selections allowed
-- prepare ruby command
set ruby_script to "ruby -e \"s=ARGV[0]; m=s.match(/(\\d{3})(\\w)/); n=m[1].to_i; a=m[2]; a.succ! if n.even?; r=sprintf('%03d',(n+1)/2)+a; puts s.sub(/\\d{3}\\w/,r);\" "
tell application "Finder"
-- process files, record errors
set counter to 0
set errors to {}
repeat with f in filesToRename
try
do shell script ruby_script & (f's name as text)
set f's name to result
set counter to counter + 1
on error
copy (f's name as text) to the end of errors
end try
end repeat
-- display report
set msg to (counter as text) & " files renamed successfully!\n"
if errors is not {} then
set AppleScript's text item delimiters to "\n"
set msg to msg & "The following files could NOT be renamed:\n" & (errors as text)
set AppleScript's text item delimiters to ""
end if
display dialog msg
end tell
Note that it will fail when the filename contains spaces.
A friend of mine wrote a Python script to do what I needed. Figured I'd post it here as an answer for anyone stumbling upon a similar problem looking for help. It is in Python though so if anyone wants to convert it to AppleScript for those that may need it go for it.
import os
import re
import shutil
def toInt(str):
try:
return int(str)
except:
return 0
filePath = "./"
extension = "png"
dirList = os.listdir(filePath)
regx = re.compile("[0-9]+a")
for filename in dirList:
ext = filename[-len(extension):]
if(ext != extension): continue
rslts = regx.search(filename)
if(rslts == None): continue
pieces = regx.split(filename)
if(len(pieces) < 2): pieces.append("")
filenumber = toInt(rslts.group(0).rstrip("a"))
newFileNum = (filenumber + 1) / 2
fileChar = "b"
if(filenumber % 2): fileChar = "a"
newFileName = "%s%03d%s%s" % (pieces[0], newFileNum, fileChar, pieces[1])
shutil.move("%s%s" % (filePath, filename), "%s%s" % (filePath, newFileName))

Categories

Resources