import os
src = "/home/user/Desktop/images/"
ext = ".jpg"
for i,filename in enumerate(os.listdir(src)):
# print(i,filename)
if filename.endswith(ext):
os.rename(src + filename, src + str(i) + ext)
print(filename, src + str(i) + ext)
else :
os.remove(src + filename)
this code will rename all the images in a folder starting with 0.jpg,1.jpg etc... and remove none jpg but what if i already had some images in that folder, let's say i had images 0.jpg, 1.jpg, 2.jpg, then i added a few others called im5.jpg and someImage.jpg.
What i want to do is adjust the code to read the value of the last image number, in this case 2 and start counting from 3 .
In other words i'll ignore the already labeled images and proceed with the new ones counting from 3.
Terse and semi-tested version:
import os
import glob
offset = sorted(int(os.path.splitext(os.path.basename(filename))[0])
for filename in glob.glob(os.path.join(src, '*' + ext)))[-1] + 1
for i, filename in enumerate(os.listdir(src), start=offset):
...
Provided all *.jpg files consist of a only a number before their extension. Otherwise you will get a ValueError.
And if there happens to be a gap in the numbering, that gap will not be filled with new files. E.g., 1.jpg, 2.jpg, 3.jpg, 123.jpg will continue with 124.jpg (which is safer anyway).
If you need to filter out filenames such as im5.jpg or someImage.jpg, you could add an if-clause to the list comprehension, with a regular expression:
import os
import glob
import re
offset = sorted(int(os.path.splitext(os.path.basename(filename))[0])
for filename in glob.glob(os.path.join(src, '*' + ext))
if re.search('\d+' + ext, filename))[-1] + 1
Of course, by now the three lines are pretty unreadable, and may not win the code beauty contest.
Related
I am really looking for a solution to this problem. I have been generating frames from a python code which i end up having into different folders as shown below,
**folder names** swimming_0, swimming_1, noswimming_0, noswimming_1.
swimming_0 noswimming_0
frame0.jpg frame0.jpg
frame1.jpg frame1.jpg
frame2.jpg frame2.jpg
swimming_1 noswimming_1
frame0.jpg frame0.jpg
frame1.jpg frame1.jpg
frame2.jpg frame2.jpg
What i expect:
In a single folder
swimming_0_0.jpg
swimming_0_1.jpg
swimming_0_2.jpg
swimming_1_0.jpg
swimming_1_1.jpg
swimming_1_2.jpg
noswimming_0_0.jpg
noswimming_0_1.jpg
noswimming_0_2.jpg
noswimming_1_0.jpg
noswimming_1_1.jpg
noswimming_1_2.jpg
The steps we need is that:
1. rename the images in each folder
2. combine the images
Python code used:
step1: renaming and adding incremental numbers
import os
folderpath = r'/swimming'
fileNumber = 1
for filename in os.listdir(folderpath):
os.rename(folderpath + '//' + filename, folderpath + "_" + str(fileNumber))
fileNumber +=1
Although this code works with my expectations for step 1 however I am looking for a more efficient way to do this. Could someone please help here.
Update:
It is also fine if we dont keep track of the filenames but atleast in that case i would expect the results to be.
swimming_0.jpg
swimming_1.jpg
swimming_2.jpg
swimming_3.jpg
swimming_4.jpg
swimming_5.jpg
noswimming_6.jpg
noswimming_7.jpg
noswimming_8.jpg
noswimming_9.jpg
noswimming_10.jpg
noswimming_11.jpg
Ok, so if you want to move files in separate folders to one you could try this:
First of you should have a structure like this:
from_here/
+ noswimming_0/
+ frame0.png
+ frame1.png
+ frame2.png
+ noswimming_1/
+ frame0.png
+ frame1.png
+ frame2.png
+ swimming_0/
+ frame0.png
+ frame1.png
+ frame2.png
+ swimming_1/
+ frame0.png
+ frame1.png
+ frame2.png
move_here/
script.py
script.py:
import os
from_path = os.getcwd() + '/from_here'
to_path = os.getcwd() + '/move_here'
for folder in os.listdir(from_path):
for file in os.listdir(os.path.join(from_path, folder)):
os.rename(os.path.join(from_path, folder, file), os.path.join(to_path, f'{folder}_{file}'))
This should now move the files from those separate folders to the one (obviously you could have more folders to move from or more files in those folders)
Trying to retrieve all the paths of the pngs in different sub folders.
All sub folders are located within a main folder - logs.
pngs = []
for idx, device in enumerate(udid):
pngs += glob.glob(os.getcwd() + "/logs/" + device + "_" + get_model_of_android_phone(device) + "/" + "*.png")
File structure
logs/123456789_SM-G920I/123456789google_search_android.png
The values in bold will change. I have added in *.png for the changing pngs.
But how do i get the paths of the pngs when i do not have an absolute path to the png file?
Update
get_model_of_android_phone(device) is a method to get the following value here.
E.g. 123456789_SM-G920I
I am thinking to remove it cause it is not really working as intended. Would like to replace the method with something like *
You can use following in simplified way to get all file names:
for name in glob.glob(os.getcwd() + "/logs/**/*.png", recursive=True):
print '\t', name
When recursive is set, ** will matches 0 or more subdirectories when followed by a separator.
If you just want to make list, use the following code snippet :
pngs = glob.glob(os.getcwd() + "/logs/**/*.png", recursive=True)
It will return a list of all png file paths.
Reference : https://docs.python.org/3/library/glob.html
for idx, device in enumerate(udid):
path_device = os.getcwd() + "/logs/" + device + "_" + get_model_of_android_phone(device) + "/"
file_list = os.listdir(path_device)
pngs = [path_device+file_png for file_png in file_list if str(file_png).endswith(".png")]
I am writing a simple Python script to tell me file size for a set of documents which I am importing from a CSV. I verified that none of the entries are over 100 characters, so this error "ValueError: scandir: path too long for Windows" does not make sense to me.
Here is my code:
# determine size of a given folder in MBytes
import os, subprocess, json, csv, platform
# Function to check if a Drive Letter exists
def hasdrive(letter):
return "Windows" in platform.system() and os.system("vol %s: 2>nul>nul" % (letter)) == 0
# Define Drive to check for
letter = 'S'
# Check if Drive doesnt exist, if not then map drive
if not hasdrive(letter):
subprocess.call(r'net use s: /del /Y', shell=True)
subprocess.call(r'net use s: \\path_to_files', shell=True)
list1 = []
# Import spreadsheet to calculate size
with open('c:\Temp\files_to_delete_subset.csv') as f:
reader = csv.reader(f, delimiter=':', quoting=csv.QUOTE_NONE)
for row in reader:
list1.extend(row)
# Define variables
folder = "S:"
folder_size = 0
# Exporting outcome
for list1 in list1:
folder = folder + str(list1)
for root, dirs, files in os.walk(folder):
for name in files:
folder_size += os.path.getsize(os.path.join(root, name))
print(folder)
# print(os.path.join(root, name) + " " + chr(os.path.getsize(os.path.join(root, name))))
print(folder_size)
From my understanding the max path size in Windows is 260 characters, so 1 driver letter + 100 character path should NOT exceed the Windows max.
Here is an example of a path: '/Document/8669/CORRESP/1722165.doc'
The folder string you're trying to walk is growing forever. Simplifying the code to the problem area:
folder = "S:"
# Exporting outcome
for list1 in list1:
folder = folder + str(list1)
You never set folder otherwise, so it starts out as S:<firstpath>, then on the next loop it's S:<firstpath><secondpath>, then S:<firstpath><secondpath><thirdpath>, etc. Simple fix: Separate drive from folder:
drive = "S:"
# Exporting outcome
for path in list1:
folder = drive + path
Now folder is constructed from scratch on each loop, throwing away the previous path, rather than concatenating them.
I also gave the iteration value a useful name (and removed the str call, because the values should all be str already).
I have some files (800+) in folder as shown below:
test_folder
1_one.txt
2_two.txt
3_three.txt
4_power.txt
5_edge.txt
6_mobile.txt
7_test.txt
8_power1.txt
9_like.txt
10_port.txt
11_fire.txt
12_water.txt
I want to rename all these files using python like this:
test_folder
001_one.txt
002_two.txt
003_three.txt
004_power.txt
005_edge.txt
006_mobile.txt
007_test.txt
008_power1.txt
009_like.txt
010_port.txt
011_fire.txt
012_water.txt
Can we do this with Python? Please guide on how to do this.
Use zfill to pad zeros
import os,glob
src_folder = r"/user/bin/"
for file_name in glob.glob(os.path.join(src_folder, "*.txt")):
lst = file_name.split('_')
if len(lst)>1:
try:
value=int(lst[0])
except ValueError:
continue
lst[0] = lst[0].zfill(3)
os.rename(file_name, '_'.join(lst))
Using zfill:
Split based on underscore _ and then use zfill to pad zero's
import os
os.chdir("test_folder")
for filename in os.listdir("."):
os.rename(filename, filename.split("_")[0].zfill(3) + filename[filename.index('_'):])
Converting to integer:
Only renames if prefix is a valid integer. Uses format(num, '03') to make sure the integer is padded with appropriate leading zero's. Renames files 1_file.txt, 12_water.txt but skips a_baa.txt etc.
import os
os.chdir("E:\pythontest")
for filename in os.listdir("."):
try:
num = int(filename.split("_")[0])
os.rename(filename, format(num, '03') + filename[filename.index('_'):])
except:
print 'Skipped ' + filename
EDIT: Both snippets ensure that if the filename contains multiple underscores then the later ones aren't snipped. So 1_file_new.txt gets renamed to 001_file_new.txt.
Examples:
# Before
'1_one.txt',
'12_twelve.txt',
'13_new_more_underscores.txt',
'a_baaa.txt',
'newfile.txt',
'onlycharacters.txt'
# After
'001_one.txt',
'012_twelve.txt',
'013_new_more_underscores.txt',
'a_baaa.txt',
'newfile.txt',
'onlycharacters.txt'
Here's a quick example to rename the files in the current directory:
import os
for f in os.listdir("."):
if os.path.isfile(f) and len(f.split("_")) > 1:
number, suffix = f.split("_")
new_name = "%03d_%s" % (int(number), suffix)
os.rename(f, new_name)
You can use glob.glob() to get a list of text files. Then use a regular expression to ensure that the file being renamed starts with digits and an underscore. Then split the file up and add leading zeros as follows:
import re
import glob
import os
src_folder = r"c:\source folder"
for filename in glob.glob(os.path.join(src_folder, "*.txt")):
path, filename = os.path.split(filename)
re_file = re.match("(\d+)(_.*)", filename)
if re_file:
prefix, base = re_file.groups()
new_filename = os.path.join(path, "{:03}{}".format(int(prefix), base))
os.rename(filename, new_filename)
The {:03} tells Python to zero pad your number to 3 digits. Python's Format Specification Mini-Language is very powerful.
Note os.path.join() is used to safely concatenate path components, so you don't have to worry about trailing separators.
I am trying to make a script which selects every .png file in a folder beginning with the letters "LG". I then want the scipt create a shapefile, replacing the "LG" with "SH", and then i want the script to buffer that shapefile and rename the buffer with the first 2 letters being "SB"!
I keep getting an error 99999 error message at line 37!
( gp.RasterToPolygon_conversion(INPUT_RASTER, Output_polygon_features, "SIMPLIFY", "VALUE") )
Can anyone see why this isnt working? I am very, very new to this and have been staring at this script pulling out my hair for days!!
Here is the script:
# Load required toolboxes...
gp.AddToolbox("C:/Program Files/ArcGIS/ArcToolbox/Toolboxes/Conversion Tools.tbx")
gp.AddToolbox("C:/Program Files/ArcGIS/ArcToolbox/Toolboxes/Analysis Tools.tbx")
# Script arguments...
folder = "D:\\J04-0083\\IMAGEFILES"
for root, dirs, filenames in os.walk(folder): # returms root, dirs, and files
for filename in filenames:
filename_split = os.path.splitext(filename) # filename and extensionname (extension in [1])
filename_zero = filename_split[0]
try:
first_2_letters = filename_zero[0] + filename_zero[1]
except:
first_2_letters = "XX"
if first_2_letters == "LG":
Output_polygon_features = "D:\\J04-0083\\ShapeFiles.gdb\\" + "SH_" + filename + ".shp"
# Process: Raster to Polygon...
INPUT_RASTER = os.path.join(root + "\\" + filename_zero + ".png")
gp.RasterToPolygon_conversion(INPUT_RASTER, Output_polygon_features, "SIMPLIFY", "VALUE")
Distance__value_or_field_ = "5 Meters"
Raster_Buffer_shp = "SB_" + filename + ".shp"
# Process: Buffer...
gp.Buffer_analysis(Output_polygon_features, Raster_Buffer_shp, Distance__value_or_field_, "FULL", "ROUND", "NONE", "")
Is .png the format that this function wants? PNG is a compressed format so I would think that something like this would be expecting an uncompressed format. In fact, since the name of the function is RasterToPolygon_conversion, wouldn't the function be expecting a raster format? The docs say that the input should be an integer raster dataset. In addition, The input raster can have any cell size and may be any valid integer raster dataset. Anyway, I suspect that is the real problem.
The last thing to check, if the file is in the correct format as per above, is if there is a field VALUE in the file.
try using a GRID or TIFF file instead of a PNG.
You can convert the PNG with:
http://webhelp.esri.com/arcgiSDEsktop/9.3/index.cfm?TopicName=raster_to_other_format_(multiple)_(conversion)
and then process it's output into the Raster to Polygon conversion.
You could also check the file path of the INPUT RASTER to make sure it looks correct by:
INPUT_RASTER = os.path.join(root + "\\" + filename_zero + ".png")
print INPUT_RASTER
gp.RasterToPolygon_conversion(INPUT_RASTER, Output_polygon_features, "SIMPLIFY", "VALUE")
There is also a method of building a filepath by:
import os
root + os.sep + filename_zero + '.png'