Created
October 18, 2017 16:44
-
-
Save Day0Dreamer/2a9ebf9ad82bad1fb37ef43afe4fd526 to your computer and use it in GitHub Desktop.
This class can generate a file sequence, clean a folder, find missing files, rename the sequence.
Expected sequence 'text00000.text'
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from os import path, makedirs, scandir, listdir, remove, rename | |
from re import search, compile | |
from warnings import warn | |
# ##################################################### CONFIG ####################################################### # | |
conf_default_working_path = '.' | |
conf_default_new_name = 'default_' | |
# #################################################################################################################### # | |
class SequenceCheck(object): | |
"""This class can generate a file sequence, clean a folder, find missing files, rename the sequence | |
Expected sequence 'text00000.text'""" | |
def __init__(self, working_path=None, new_name=None): | |
self.working_path = working_path or conf_default_working_path | |
self.new_name = new_name or conf_default_new_name | |
self.working_set = [] | |
self.working_set_int = [] | |
self.most_common_ext = None | |
def generate_placeholder_sequence(self, | |
prefix='image_', suffix='.jpg', | |
range_start=0, range_stop=99, step=1, | |
empty_folder_check=True): | |
"""Follows a pattern of 'prefix+number+suffix' to generate files, | |
makes a new folder and requires it to be empty""" | |
makedirs(self.working_path, exist_ok=True) | |
try: | |
if empty_folder_check: | |
next(scandir(self.working_path)) # If there is a file inside | |
raise FileExistsError('{} is not empty'.format(path.abspath(self.working_path))) | |
else: | |
raise StopIteration | |
except StopIteration: | |
pass # If there is nothing inside | |
except FileExistsError: | |
warn('{} is not empty'.format(path.abspath(self.working_path))) | |
return | |
for i in range(range_start, range_stop, step): # Make a bunch of empty files | |
file_path = path.join(path.abspath(self.working_path), str(prefix) + str(i) + str(suffix)) | |
open(file_path, 'w').close() | |
def clean_working_path(self): | |
"""Simply delete everything inside the working path""" | |
[remove(file.path) for file in scandir(self.working_path)] | |
def analyse_sequence(self): | |
"""Analyse the folder contents to guess what is the most likely sequence""" | |
dir_content = listdir(self.working_path) | |
ls = [path.splitext(file) for file in dir_content] # Get [file names, extensions] | |
ext = set([file_item[1] for file_item in ls]) # Get extensions of files | |
ext_dict = {} # Count files by extension | |
for i in list(ext): | |
ext_dict[i] = [i[1] for i in ls].count(i) | |
self.most_common_ext = max(ext_dict, key=(lambda key: ext_dict[key])) | |
# Get most likely sequence | |
self.working_set = [file for file in dir_content if path.splitext(file)[1] == self.most_common_ext] | |
# Extract ints from file names | |
self.working_set_int = [] | |
frame_number_re = compile('[0-9]+\.') | |
start, end = search(frame_number_re, self.working_set[0]).span() | |
for file in self.working_set: | |
frame_number_extracted = file[start:end-1] | |
if frame_number_extracted.isdigit(): | |
self.working_set_int.append(int(frame_number_extracted)) | |
def check_missing_frames(self): | |
self.analyse_sequence() | |
# Check for missing frames | |
for frame_n_int in range(self.working_set_int[1], self.working_set_int[-1]): | |
if frame_n_int not in self.working_set_int: | |
print('Frame #{} is missing'.format(frame_n_int)) | |
def rename_sequence(self, new_name=None, zfill=3): | |
if new_name: | |
self.new_name = new_name | |
self.analyse_sequence() | |
# Create the new names | |
assembled_names_list = [] | |
for i in self.working_set_int: | |
assembled_name = str(self.new_name)+str(i).zfill(zfill)+str(self.most_common_ext) | |
assembled_names_list.append(assembled_name) | |
# Churning through the new names list and renaming them | |
for i in zip(self.working_set, assembled_names_list): | |
if i[0] == i[1]: | |
print('Names are equal') | |
break | |
else: | |
self.new_name = path.join(self.working_path, i[0]), path.join(self.working_path, i[1]) | |
try: | |
rename(*self.new_name) # *unpacking a tuple into two arguments | |
print('Rename successful: {} -> {}'.format(*self.new_name)) # *unpacking a tuple into two arguments | |
except OSError: | |
print('Renaming went wrong') | |
if __name__ == '__main__': | |
w_dir = input('Tell me the folder [DEFAULT = {}]\n'.format(path.abspath(path.curdir))) | |
sc = SequenceCheck(w_dir) | |
while 1: | |
gen_quest = input('Generate sample sequence? [Y/N]\n') | |
if gen_quest.upper() == 'Y': | |
sc.generate_placeholder_sequence(range_stop=4, empty_folder_check=False) | |
break | |
while 1: | |
ren_quest = input('Rename the sequence? [Y/N]\n') | |
if ren_quest.upper() == 'Y': | |
sc.rename_sequence() | |
break | |
else: | |
break |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment