I have this code below trying to remove the leading characters of a string by using an indicator to where to stop the trim.
I just want to know if there are some better ways to do this.
#Get user's input: file_name
file_name = str.casefold(input("Filename: ")).strip()
#Get the index of "." from the right of the string
i = file_name.rfind(".")
# getting the file extension from the index i
ext = file_name[i+1:]
# Concatinating "image/" with the extractted file extension
new_fname = "image/" + ext
print(new_fname)
Looking at your code you can shorten it to:
file_name = input("Filename: ")
new_fname = f"image/{file_name.rsplit('.', maxsplit=1)[-1]}"
print(new_fname)
Related
The goal is to create a naming system for duplicate strings.
If the name is hotdog.jpg and I want to make a duplicate and that the next string is hotdog_1.jpg. And so on. But the problem I'm facing is that if you make a duplicate of hotdog_1.jpg we get hotdog_1_1.jpg. I tried to just check if the string ends with "(underscore) + number". But then the problem is that the string could also have "(underscore) + number + number". like hotdog_13.jpg.
is there any good way to implement this?
for current_image_name in self.images_names:
extension = os.path.splitext(current_image_name)[1]
current_image_name = os.path.splitext(current_image_name)[0]
if current_image_name[-2] == '_' and current_image_name[-1].isdigit():
self.images_names.insert(self.current_index + 1, current_image_name[:-1] + str(int(self.images_names[self.current_index][-1]) + 1) + extension)
name_change = True
if not name_change:
self.images_names.insert(self.current_index + 1, self.images_names[self.current_index] + '_1')
You can do this with a simple method that does some string magic.
EDITED after reading the comments on the question. Added a method to handle lists
code
def inc_filename(filename: str) -> str:
if "." in filename:
# set extension
extension = f""".{filename.split(".")[-1]}"""
# remove extension from filename
filename = ".".join(filename.split(".")[:-1])
else:
# set extension to empty if not included
extension = ""
try:
# try to set the number
# it will throw a ValueError if it doesn't have _1
number = int(filename.split("_")[-1]) +1
newfilename = "_".join(filename.split("_")[:-1])
except ValueError:
# catch the ValueError and set the number to 1
number = 1
newfilename = "_".join(filename.split("_"))
return f"{newfilename}_{number}{extension}"
def inc_filelist(filelist: list) -> list:
result = []
for filename in filelist:
filename = inc_filename(filename)
while filename in filelist or filename in result:
filename = inc_filename(filename)
result.append(filename)
return result
print(inc_filename("hotdog_1"))
print(inc_filename("hotdog"))
print(inc_filename("hotdog_1.jpg"))
print(inc_filename("hotdog.jpg"))
print(inc_filename("ho_t_dog_15.jpg"))
print(inc_filename("hotdog_1_91.jpg"))
filelist = [
"hotdog_1.jpg",
"hotdog_2.jpg",
"hotdog_3.jpg",
"hotdog_4.jpg"
]
print(inc_filelist(filelist))
output
hotdog_2
hotdog_1
hotdog_2.jpg
hotdog_1.jpg
ho_t_dog_16.jpg
hotdog_1_92.jpg
['hotdog_5.jpg', 'hotdog_6.jpg', 'hotdog_7.jpg', 'hotdog_8.jpg']
I'm trying to change filenames like WINDOW.txt to lowercase but then I also need to change the extension .txt to uppercase. I am thinking I can just change the entire thing to lowercase as the extension is already lowercase and then using something like .endswith() to change the extension to uppercase but I can't seem to figure it out. I know this may seem simple to most so thank you for your patience.
This one handles filenames, paths across different operating systems:
import os.path
def lower_base_upper_ext(path):
"""Filename to lowercase, extension to uppercase."""
path, ext = os.path.splitext(path)
head, tail = os.path.split(path)
return head + tail.lower() + ext.upper()
It leaves possible directory names untouched, just the filename portion is lower-cased and extension upper-cased.
oldname='HeLlO.world.TxT'
if '.' in oldname:
(basename, ext) = oldname.rsplit('.', 1)
newname = basename.lower() + '.' + ext.upper()
else:
newname = oldname.lower()
print(f'{oldname} => {newname}')
...properly emits:
HeLlO.world.TxT => hello.world.TXT
name = "MyFile.txt"
new_name = name.rsplit(sep= ".", maxsplit=1)
print(new_name[0].lower()+"."+new_name[1].upper())
filename = "WINDOW.txt"
filename = filename.split('.')
filename = ".".join(filename[0:-1]).lower() + '.' + filename[-1].upper()
print(filename)
>> window.TXT
filename = "foo.bar.maz.txt"
filename = filename.split('.')
filename = ".".join(filename[0:-1]).lower() + '.' + filename[-1].upper()
print(filename)
>> foo.bar.maz.TXT
If I read the question correctly, it wants the lowercase name and upper case file extension, which is weird, but here is a simple solution.
filename = "WINDOW.txt"
ext_ind = filename.rindex('.')
filename = filename[0:ext_ind].lower() + '.' + filename[ext_ind+1:len(filename)].upper()
print(filename)
>> window.TXT
I have a bit of code that accepts a .csv with a list of filenames as an input, then breaks the filename down into its component parts and re-orders them along with some additional characters.
Input Example:
3006419_3006420_ENG_FRONT.jpg
Output Example:
;E3006419_3006420_FRONT_Image_Container;
However, I'd like to make the portion of the for loop that splits up the filename into a function that I can call elsewhere, so that I can re-use it in a second for loop that outputs in a different format. When I try to define a function, though, it seems I have a scoping error with my variables and can't use them in my output.write statement.
Working Code
from csv import reader
import sys
if len(sys.argv) != 2:
print('USAGE ERROR:\nRun like "python <script.py> <input file.csv>"') #error message if code is not run with correct number of arguments
exit()
file = open(sys.argv[1]) #open input file
output = open('output.impex','w+') #define output impex file
for line in file:
nameAndExtension = line.split('.') #split file into filename and file extension
name = nameAndExtension[0]
extension = nameAndExtension[1].replace('\n','') #save file extension as variable extension and remove \n
elements = name.split('_') #split filename into constituent elements. Filenames are formatted as PARENTSKU_CHILDSKU_LANG_ANGLE.extension, eg '3006419_3006420_ENG_FRONT.jpg'
parentSKU = elements[0]
childSKU = elements[1]
lang = elements[2]
angle = elements[3]
output.write(";E" + parentSKU + "_" + childSKU + "_" + angle + '_Image_Container;\n')
Non-Working Code:
from csv import reader
import sys
if len(sys.argv) != 2:
print('USAGE ERROR:\nRun like "python <script.py> <input file.csv>"') #error message if code is not run with correct number of arguments
exit()
file = open(sys.argv[1]) #open input file
output = open('output.impex','w+') #define output impex file
def lineSplitting(x):
nameAndExtension = x.split('.') #split file into filename and file extension
name = nameAndExtension[0]
extension = nameAndExtension[1].replace('\n','') #save file extension as variable extension and remove \n
elements = name.split('_') #split filename into constituent elements. Filenames are formatted as PARENTSKU_CHILDSKU_LANG_ANGLE.extension, eg '3006419_3006420_ENG_FRONT.jpg'
parentSKU = elements[0]
childSKU = elements[1]
lang = elements[2]
angle = elements[3]
for line in file:
lineSplitting(line)
output.write(";E" + parentSKU + "_" + childSKU + "_" + angle + '_Image_Container;\n')
I get "NameError: name 'parentSKU' is not defined" I think because the of the variable scope - but I don't know what I need to do to make the variable re-usable in the for-loop. What do I need to do to make all that splitting and variable definition into a function?
you should return your value from the function
def lineSplitting(x):
nameAndExtension = x.split('.') #split file into filename and file extension
name = nameAndExtension[0]
extension = nameAndExtension[1].replace('\n','') #save file extension as variable extension and remove \n
elements = name.split('_') #split filename into constituent elements. Filenames are formatted as PARENTSKU_CHILDSKU_LANG_ANGLE.extension, eg '3006419_3006420_ENG_FRONT.jpg'
parentSKU = elements[0]
childSKU = elements[1]
lang = elements[2]
angle = elements[3]
return parentSKU,childSKU,angle
and the next code will call the function
for line in file:
parentSKU,childSKU,angle =lineSplitting(line)
output.write(";E" + parentSKU + "_" + childSKU + "_" + angle + '_Image_Container;\n')
To secure uploaded image names, I'd like to strip out image's filenames from anything but string.ascii_letters , string.digits, dot and (one) whitespace.
So I'm wondering what is the best method to check a text against other characters?
import re
import os
s = 'asodgnasAIDID12313%*(#&(!$ 1231'
result = re.sub('[^a-zA-Z\d\. ]|( ){2,}','',s )
if result =='' or os.path.splitext(result)[0].isspace():
print "not a valid name"
else:
print "valid name"
EDIT:
changed it so it will also whitelist only one whitespace + added import re
Not sure if it's what you need but give it a try:
import sys, os
fileName, fileExtension = os.path.splitext('image 11%%22.jpg')
fileExtension = fileExtension.encode('ascii', 'ignore')
fileName = fileName.encode('ascii', 'ignore')
if fileExtension[1:] in ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'tiff', 'tga']:
fileName = ''.join(e for e in fileName if e.isalnum())
print fileName+fileExtension
#image1122.jpg
else:
print "Extension not supported"
isalnum()
https://docs.python.org/2/library/stdtypes.html#str.isalnum
I wouldn't use regex for this. The only tricky requirement is the single space, but that can be done, too.
import string
whitelist = set(string.ascii_letters + string.digits)
good_filename = "herearesomelettersand123numbers andonespace"
bad_filename = "symbols&#! and more than one space"
def strip_filename(fname, whitelist):
"""Strips a filename
Removes any character from string `fname` and removes all but one
whitespace.
"""
whitelist.add(" ")
stripped = ''.join([ch for ch in fname if ch in whitelist])
split = stripped.split()
result = " ".join([split[0], ''.join(split[1:])])
return result
Then call it with:
good_sanitized = strip_filename(good_filename, whitelist)
bad_sanitized = strip_filename(bad_filename, whitelist)
print(good_sanitized)
# 'herearesomelettersand123numbers andonespace'
print(bad_sanitized)
# 'symbols andmorethanonespace'
My code
import os.path #gets the module
beginning = input("Enter the file name/path you would like to upperify: ")
inFile = open(beginning, "r")
contents = inFile.read()
moddedContents = contents.upper() #makes the contents of the file all caps
head,tail = os.path.split(beginning) #supposed to split the path
new_new_name = "UPPER" + tail #adds UPPER to the file name
final_name = os.path.join(head + new_new_name) #rejoins the path and new file name
outFile = open(final_name, "w") #creates new file with new capitalized text
outFile.write(moddedContents)
outFile.close()
I'm just trying to change the file name to add UPPER to the beginning to the file name via os.path.split(). Am I doing something wrong?
Change
final_name = os.path.join(head + new_new_name)
to
final_name = head + os.sep + new_new_name
head from os.path.split doesn't have a trailing slash in the end. When you join the head and new_new_name by concatenating them
head + new_new_name
you don't add that missing slash, so the whole path becomes invalid:
>>> head, tail = os.path.split('/etc/shadow')
>>> head
'/etc'
>>> tail
'shadow'
>>> head + tail
'/etcshadow'
The solution is to use os.path.join properly:
final_name = os.path.join(head, new_new_name)