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']
Related
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)
Does Python have any built-in functionality to add a number to a filename if it already exists?
My idea is that it would work the way certain OS's work - if a file is output to a directory where a file of that name already exists, it would append a number or increment it.
I.e: if "file.pdf" exists it will create "file2.pdf", and next time "file3.pdf".
I ended up writing my own simple function for this. Primitive, but gets the job done:
def uniquify(path):
filename, extension = os.path.splitext(path)
counter = 1
while os.path.exists(path):
path = filename + " (" + str(counter) + ")" + extension
counter += 1
return path
In a way, Python has this functionality built into the tempfile module. Unfortunately, you have to tap into a private global variable, tempfile._name_sequence. This means that officially, tempfile makes no guarantee that in future versions _name_sequence even exists -- it is an implementation detail.
But if you are okay with using it anyway, this shows how you can create uniquely named files of the form file#.pdf in a specified directory such as /tmp:
import tempfile
import itertools as IT
import os
def uniquify(path, sep = ''):
def name_sequence():
count = IT.count()
yield ''
while True:
yield '{s}{n:d}'.format(s = sep, n = next(count))
orig = tempfile._name_sequence
with tempfile._once_lock:
tempfile._name_sequence = name_sequence()
path = os.path.normpath(path)
dirname, basename = os.path.split(path)
filename, ext = os.path.splitext(basename)
fd, filename = tempfile.mkstemp(dir = dirname, prefix = filename, suffix = ext)
tempfile._name_sequence = orig
return filename
print(uniquify('/tmp/file.pdf'))
I was trying to implement the same thing in my project but #unutbu's answer seemed too 'heavy' for my needs so I came up with following code finally:
import os
index = ''
while True:
try:
os.makedirs('../hi'+index)
break
except WindowsError:
if index:
index = '('+str(int(index[1:-1])+1)+')' # Append 1 to number in brackets
else:
index = '(1)'
pass # Go and try create file again
Just in case someone stumbled upon this and requires something simpler.
If all files being numbered isn't a problem, and you know beforehand the name of the file to be written, you could simply do:
import os
counter = 0
filename = "file{}.pdf"
while os.path.isfile(filename.format(counter)):
counter += 1
filename = filename.format(counter)
recently I encountered the same thing and here is my approach:
import os
file_name = "file_name.txt"
if os.path.isfile(file_name):
expand = 1
while True:
expand += 1
new_file_name = file_name.split(".txt")[0] + str(expand) + ".txt"
if os.path.isfile(new_file_name):
continue
else:
file_name = new_file_name
break
Let's say you already have those files:
This function generates the next available non-already-existing filename, by adding a _1, _2, _3, ... suffix before the extension if necessary:
import os
def nextnonexistent(f):
fnew = f
root, ext = os.path.splitext(f)
i = 0
while os.path.exists(fnew):
i += 1
fnew = '%s_%i%s' % (root, i, ext)
return fnew
print(nextnonexistent('foo.txt')) # foo_3.txt
print(nextnonexistent('bar.txt')) # bar_1.txt
print(nextnonexistent('baz.txt')) # baz.txt
Since the tempfile hack A) is a hack and B) still requires a decent amount of code anyway, I went with a manual implementation. You basically need:
A way to Safely create a file if and only if it does not exist (this is what the tempfile hack affords us).
A generator for filenames.
A wrapping function to hide the mess.
I defined a safe_open that can be used just like open:
def iter_incrementing_file_names(path):
"""
Iterate incrementing file names. Start with path and add " (n)" before the
extension, where n starts at 1 and increases.
:param path: Some path
:return: An iterator.
"""
yield path
prefix, ext = os.path.splitext(path)
for i in itertools.count(start=1, step=1):
yield prefix + ' ({0})'.format(i) + ext
def safe_open(path, mode):
"""
Open path, but if it already exists, add " (n)" before the extension,
where n is the first number found such that the file does not already
exist.
Returns an open file handle. Make sure to close!
:param path: Some file name.
:return: Open file handle... be sure to close!
"""
flags = os.O_CREAT | os.O_EXCL | os.O_WRONLY
if 'b' in mode and platform.system() == 'Windows':
flags |= os.O_BINARY
for filename in iter_incrementing_file_names(path):
try:
file_handle = os.open(filename, flags)
except OSError as e:
if e.errno == errno.EEXIST:
pass
else:
raise
else:
return os.fdopen(file_handle, mode)
# Example
with safe_open("some_file.txt", "w") as fh:
print("Hello", file=fh)
I haven't tested this yet but it should work, iterating over possible filenames until the file in question does not exist at which point it breaks.
def increment_filename(fn):
fn, extension = os.path.splitext(path)
n = 1
yield fn + extension
for n in itertools.count(start=1, step=1)
yield '%s%d.%s' % (fn, n, extension)
for filename in increment_filename(original_filename):
if not os.isfile(filename):
break
This works for me.
The initial file name is 0.yml, if it exists, it will add one until meet the requirement
import os
import itertools
def increment_filename(file_name):
fid, extension = os.path.splitext(file_name)
yield fid + extension
for n in itertools.count(start=1, step=1):
new_id = int(fid) + n
yield "%s%s" % (new_id, extension)
def get_file_path():
target_file_path = None
for file_name in increment_filename("0.yml"):
file_path = os.path.join('/tmp', file_name)
if not os.path.isfile(file_path):
target_file_path = file_path
break
return target_file_path
import os
class Renamer():
def __init__(self, name):
self.extension = name.split('.')[-1]
self.name = name[:-len(self.extension)-1]
self.filename = self.name
def rename(self):
i = 1
if os.path.exists(self.filename+'.'+self.extension):
while os.path.exists(self.filename+'.'+self.extension):
self.filename = '{} ({})'.format(self.name,i)
i += 1
return self.filename+'.'+self.extension
I found that the os.path.exists() conditional function did what I needed. I'm using a dictionary-to-csv saving as an example, but the same logic could work for any file type:
import os
def smart_save(filename, dict):
od = filename + '_' # added underscore before number for clarity
for i in np.arange(0,500,1): # I set an arbitrary upper limit of 500
d = od + str(i)
if os.path.exists(d + '.csv'):
pass
else:
with open(d + '.csv', 'w') as f: #or any saving operation you need
for key in dict.keys():
f.write("%s,%s\n"%(key, dictionary[key]))
break
Note: this appends a number (starting at 0) to the file name by default, but it's easy to shift that around.
This function validates if the file name exists using regex expresion and recursion
def validate_outfile_name(input_path):
filename, extension = os.path.splitext(input_path)
if os.path.exists(input_path):
output_path = ""
pattern = '\([0-9]\)'
match = re.search(pattern, filename)
if match:
version = filename[match.start() + 1]
try: new_version = int(version) + 1
except: new_version = 1
output_path = f"{filename[:match.start()]}({new_version}){extension}"
output_path = validate_outfile_name(output_path)
else:
version = 1
output_path = f"{filename}({version}){extension}"
return output_path
else:
return input_path
I've implemented a similar solution with pathlib:
Create file-names that match the pattern path/<file-name>-\d\d.ext. Perhaps this solution can help...
import pathlib
from toolz import itertoolz as itz
def file_exists_add_number(path_file_name, digits=2):
pfn = pathlib.Path(path_file_name)
parent = pfn.parent # parent-dir of file
stem = pfn.stem # file-name w/o extension
suffix = pfn.suffix # NOTE: extension starts with '.' (dot)!
try:
# search for files ending with '-\d\d.ext'
last_file = itz.last(parent.glob(f"{stem}-{digits * '?'}{suffix}"))
except:
curr_no = 1
else:
curr_no = int(last_file.stem[-digits:]) + 1
# int to string and add leading zeros
curr_no = str(last_no).zfill(digits)
path_file_name = parent / f"{stem}-{curr_no}{suffix}"
return str(path_file_name)
Pls note: That solution starts at 01 and will only find file-pattern containing -\d\d!
def create_file():
counter = 0
filename = "file"
while os.path.isfile(f"dir/{filename}{counter}.txt"):
counter += 1
print(f"{filename}{counter}.txt")
A little bit later but there is still something like this should work properly, mb it will be useful for someone.
You can use built-in iterator to do this ( image downloader as example for you ):
def image_downloader():
image_url = 'some_image_url'
for count in range(10):
image_data = requests.get(image_url).content
with open(f'image_{count}.jpg', 'wb') as handler:
handler.write(image_data)
Files will increment properly. Result is:
image.jpg
image_0.jpg
image_1.jpg
image_2.jpg
image_3.jpg
image_4.jpg
image_5.jpg
image_6.jpg
image_7.jpg
image_8.jpg
image_9.jpg
Easy way for create new file if this name in your folder
if 'sample.xlsx' in os.listdir('testdir/'):
i = 2
while os.path.exists(f'testdir/sample ({i}).xlsx'):
i += 1
wb.save(filename=f"testdir/sample ({i}).xlsx")
else:
wb.save(filename=f"testdir/sample.xlsx")
I want to batch rename a set of files in a folder with specific conditions, which is (add prefix, start from a specific number and increase in +1 series, skip a specific number in the series, add files with same number using an underscore)
I have a set of scanned document files, starting from a specif number let's say 10 and increments with 1. Ex 10,11,12,...
.But some files will be missing for ex maybe 13 will be missing, so need an option to skip that 13 and start with 14. Also some documents will be 2 pages, so need to put underscore to distinguish. For ex 15th document is 2 pages, so need to put 15_2 for the second file.
UPDATE1: I have fixed almost everything, now its working perfectly, but now i need to do two things
1. Need a while loop to check whether the entered number for skip is less than or equal to x.
I have no idea on how to do the below condtion:
Also some documents will be 2 pages, so need to put underscore to distinguish. For ex 15th document is 2 pages, so need to put 15_2 for the second file.
UPDATE 2 : I have added the condition for when there in repeated files but syntax error as below
UPDATE 3 : My friend helped me to get rid of the syntax error.
UPDATE 4 : My friend helped with some logic and i have solved the puzzle, updated here for reference. Thank you Jishnu
line 20
i -= 1 and dst = pre.upper() + str(i) + "_2.pdf"
import os
pre = str(input("Enter prefix : "))
while pre not in ("cin", "CIN", "CRT", "crt", "inv", "INV", "DO", "do"):
pre = str(input("Please check the entered prefix and try again : "))
x = int(input("Enter first no : "))
skip = int(input("Skip : "))
rt = int(input("Enter repeating number"))
rt = rt + 1
def main():
i = x
for filename in os.listdir("C:/Users/Ajeshhome/Desktop/scan/"):
if skip == i:
i += 1
dst = pre.upper() + str(i) + ".pdf"
src = 'C:/Users/Ajeshhome/Desktop/scan/' + filename
dst = 'C:/Users/Ajeshhome/Desktop/scan/' + dst
os.rename(src, dst)
i += 1
elif rt == i:
dst = pre.upper() + str(i-1) + "_2.pdf"
src = 'C:/Users/Ajeshhome/Desktop/scan/' + filename
dst = 'C:/Users/Ajeshhome/Desktop/scan/' + dst
os.rename(src, dst)
i += 1
else:
dst = pre.upper() + str(i) + ".pdf"
src = 'C:/Users/Ajeshhome/Desktop/scan/' + filename
dst = 'C:/Users/Ajeshhome/Desktop/scan/' + dst
os.rename(src, dst)
i += 1
def lis():
path = 'C:/Users/Ajeshhome/Desktop/scan/'
files = []
# r=root, d=directories, f = files
for r, d, f in os.walk(path):
for file in f:
if '.pdf' in file:
files.append(os.path.join(r, file))
for f in files:
print(f)
# Driver Code
if __name__ == '__main__':
# Calling main() function
main()
lis()
os.system('pause')
I'm not sure how to solve everything you're asking about. But here's a start: reliable prefix selection. Here's the whole code:
PREFIXES = {
"CIN",
"CRT",
"DO",
"INV",
}
def ask_prefix():
prefixes = sorted(PREFIXES)
for i, prefix in enumerate(prefixes, start=1):
print(f'{i}) {prefix}')
while True:
reply = input('Select prefix: ').strip().upper()
try:
index = int(reply) - 1
except ValueError:
if reply in PREFIXES:
return reply
else:
if 0 <= index < len(prefixes):
return prefixes[index]
print(f'{reply!r} is not a valid prefix.')
pre = ask_prefix()
A global set for all valid prefixes:
PREFIXES = {
"CIN",
"CRT",
"DO",
"INV",
}
Now let's look at ask_prefix(). The first line creates a sorted list from the PREFIXES so they print out in a nice order. Then:
for i, prefix in enumerate(prefixes, start=1):
print(f'{i}) {prefix}')
Use enumerate to number the prefixes then print out the number and prefix to create a menu. Next, enter an infinite loop (while True:), which only breaks when the user enters or selects a valid prefix.
Ask the user for a prefix or a number from the menu and clean up the input:
reply = input('Select prefix: ').strip().upper()
Try the reply as an index:
try:
index = int(reply) - 1
except ValueError:
...
else:
if 0 <= index < len(prefixes):
return prefixes[index]
If it doesn't work as an index, try it as a prefix:
if reply in PREFIXES:
return reply
I want to compare the files of two zip folders.
Copy only if the magnitude is greater when there is already a zip at the end when missing an equal name, copy the file.
Only Name is compared not a date: es--> Campobasso[CB]-Molise
Folder DirTemp ZIP:
Campobasso[CB]-Molise__02-02-2016.zip
Folder DirArc ZIP:
Foggia[FG]-Puglia__22-01-2016.zip
Roma[RM]-Lazio__20-01-2016.zip
Folder DirArcScartati,
They are the zip that if found and are smaller are put another folder
This is my code, but work partially, I can not to copy the file (if not exist) at the end of the control, with list.
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import os,glob,shutil
DirTemp = "/var/www/vhosts/anon_ftp/incoming/"
DirArc = "/var/www/vhosts/settings/BackupDTT/"
DirArcScartati = "/var/www/vhosts/settings/BackupDTT_scartati/"
ExtFile = ".zip"
def ControlFile():
# Controllo i nuovi file zip
listnew=[]
#print "Avvio copia"
for name in glob.glob(DirTemp + "*" + ExtFile):
listnew.append((name.replace(DirTemp,"").replace(ExtFile,"").split("__")[0],name))
#print "Nome: "+ str(listnew)
for oldname in glob.glob(DirArc + "*" + ExtFile):
#print "Setting Esistente: "+oldname
namesplit = oldname.replace(DirArc,"").replace(ExtFile,"").split("__")[0]
for newname in listnew:
#print "New Nome: "+str(newname[0])
print namesplit
if namesplit == newname[0]:
if os.path.getsize(newname[1]) >= os.path.getsize(oldname):
print ("trasferire file" + newname[1] + " >>> " + oldname)
shutil.copy2(newname[1],DirArc)
os.remove(oldname)
#os.remove(newname[1])
break
elif os.path.getsize(newname[1]) <= os.path.getsize(oldname):
print ("File più piccolo---\nFileNuovo: " + str(os.path.getsize(newname[1])) + " FileVecchio: " + str(os.path.getsize(oldname)))
shutil.copy2(newname[1],DirArcScartati)
#os.remove(newname[1])
break
else:
for newname in listnew:
print ("Nuova città trasferisco il file: " + newname[1])
shutil.copy2(newname[1],DirArc)
#os.remove(newname[1])
break
ControlFile()
The following approach might be a bit easier to follow:
def get_file_dictionary(folder):
""" Return a dictionary of zip files in the given folder as tuples in the form: (basename, full path, size) """
return {os.path.splitext(os.path.split(x)[1])[0].split('__')[0] : (x, os.path.getsize(x)) for x in glob.glob(folder + '*.zip')}
DirTemp = "/var/www/vhosts/italysat.eu/anon_ftp/incoming/"
DirArc = "/var/www/vhosts/italysat.eu/settings.italysat.eu/BackupDTT/"
DirArcScartati = "/var/www/vhosts/italysat.eu/settings.italysat.eu/BackupDTT_scartati/"
incoming = get_file_dictionary(DirTemp)
existing = get_file_dictionary(DirArc)
for base_name_inc, (full_name_inc, size_inc) in incoming.items():
try:
full_name_exist, size_exist = existing[base_name_inc]
if size_inc > size_exist:
print "Transfer {} -> {}".format(full_name_inc, full_name_exist)
os.remove(full_name_exist)
shutil.copy2(full_name_inc, full_name_exist)
else:
discard = os.path.join(DirArcScartati, os.path.split(full_name_inc)[1])
print "Discard {} -> {}".format(full_name_inc, discard)
shutil.copy2(full_name_inc, discard)
except KeyError, e:
new_entry = os.path.join(DirArc, os.path.split(full_name_inc)[1])
print "Transfer new {} -> {}".format(full_name_inc, new_entry)
os.remove(full_name_inc)
It first creates to dictionaries containing all of the entries in the incoming folder and the archive folder. It then iterates over the incoming dictionary to see if an entry is in the archive. If it is, it checks the two sizes, if not it copies the new entry.
The dictionaries are stored with the key being your base name (without dates) and the values being the full path name and the file size.
I'm new here so bare in mind that and I hope my questions are clearly asked for you lot to help me out. I am trying to alter Brent Tylers Dropbox script so that I will be able to list Python under Python, Mel under Mel and so on(eventually plugins and other files too but not for now)
Ok so my directory is like so:
1.
sf=C:/users/scripts/ a.py + b.mel
pf=C:/users/scripts/Python/c.py
mf=C:/users/scripts/Mel/d.mel
(These are the folders my scripts will be placed in)
Code :
absoluteFiles = []
relativeFiles = []
folders = []
allFiles = []
currentFile = ''
for root, dirs, files in os.walk(sf):
for x in files:
correct = root.replace('\\', '/')
currentFile = (correct + '/' + x)
allFiles.append(currentFile)
if currentFile.endswith('.mel'):
relativeFiles.append(currentFile.replace((mf + '/'), ""))
if currentFile.endswith('.py'):
relativeFiles.append(currentFile.replace((pf + '/'), ""))
relativeFiles.sort()
for relativeFile in relativeFiles:
split = relativeFile.split('/')
fileName = split[-1].split('.')
i=0
while i<(len(split)):
### Create Folders ###
if i==0 and len(split) != 1:
if cmds.menu(split[i] ,ex=1) == 0:
cmds.menuItem(split[i], p=PadraigsTools, bld=1, sm=1, to=1, l=split[i])
if i > 0 and i < (len(split)-1):
if cmds.menu(split[i] ,ex=1) == 0:
cmds.menuItem(split[i], p=split[i-1], bld=1, sm=1, to=1, l=split[i])
### Create .mel Files ###
if fileName[-1] == 'mel':
if i==len(split)-1 and len(split) > 1:
scriptName = split[-1].split('.')
temp1 = 'source ' + '"' + sf + '/' + relativeFile + '"; ' + scriptName[0]
command = '''mel.eval(''' + "'" + temp1 + '''')'''
cmds.menuItem(split[i], p=split[i-1], c=command, l=split[i])
if i==len(split)-1 and len(split) == 1:
scriptName = split[-1].split('.')
temp1 = 'source ' + '"' + sf + '/' + relativeFile + '"; ' + scriptName[0]
command = '''mel.eval(''' + "'" + temp1 + '''')'''
cmds.menuItem(split[i], p=Mel, c=command, l=split[i])
### Create .py Files ###
if fileName[-1] == 'py':
if i==len(split)-1 and len(split) > 1:
command = 'import ' + fileName[0] + '\n' + fileName[0] + '.' + fileName[0]+ '()'
cmds.menuItem(split[i], p=split[i-1], c=command, l=split[i])
if i==len(split)-1 and len(split) == 1:
command = 'import ' + fileName[0] + '\n' + fileName[0] + '.' + fileName[0]+ '()'
cmds.menuItem(split[i], p=Python, c=command, l=split[i])
i+=1
So far I can print out individually (sf, pf, mf) to the corresponding Directory but I cant list out everything at once and the files under sf will not show at all. regarding the folders created it ends up very odd. sometimes i would get a duplicate folder as a submenu and if i use sf it give me C:/.
After days and hours of research trying to mend this script I have found no answer including
from itertools import chain
paths = (mf, sf, pf)
for path, dirs, files in chain.from_iterable(os.walk(path) for path in paths):
::QUESTION::
Is there a way i can put this together sanely so that new folders will show up with their contents on refresh as a submenu and the files will show up and allow me to execute them from their corresponding submenu.
I would appreciate any help possible including down votes haha. And bare in mind I don't want you to hand me the answer on a golden spoon because I wont know what is corrected or needs to be :)
Thanks Greatly
-- Padraig
There's a couple of things you can do to simplify things a bit.
First, it's a good idea to make this as data-driven as possible so you don't have to re-write it if your needs change. This does more or less what you do, but collects the results into a dictionary where the key are the root paths you supplied and the values are lists of relative paths:
def find_files(root, extensions = ('mel', 'py')):
def clean_path(*p):
return "/".join(p).replace('\\', '/')
for root, _, files in os.walk(root):
used = [f for f in files if f.split(".")[-1] in extensions]
for u in used:
yield clean_path(root, u)
def relativize(abs, roots):
low_roots = map (str.lower, roots) # all lower for comparison
for root, low_root in zip(roots,low_roots):
if abs.lower().startswith(low_root):
return root, abs[len(root):]
return ("", abs)
relative_paths = find_files('c:/users/scripts')
root_dict = {}
for item in relative_paths :
folder, file = relativize(item, ('C:/users/scripts/Python/', 'C:/users/scripts/Mel/', 'C:/users/scripts/'))
if not folder in root_dict:
root_dict[folder] = []
root_dict[folder].append(file)
So now you have a dictionary with a bunch of root folders and lists of relative paths (files that were not in any relative path you supplied are keyed to empty string and show up as absolute paths). You can make the menus in a very generic way because they are all in the same format. If you need the entire list, you can get it like this:
results = []
for each_root in root_dict:
for relpath in root_dict[each_root]:
results.append(each_root + relpath)
For creating the actual menus, you want to use a single function and bind it to the filename for each menu item as you make it. This is a slightly tricky topic (more detail here). The easy way to do this is to use a functools.partial object, which bundles a command and a bunch of arguments into an object which looks like a function: you can create a partial and attach it to the command of your menu items so they all call the same function with their individual arguments. Here's a simple example using the variables from above and a menubar; you can see how to adapt it to other kinds of menus pretty easily:
from functools import partial
# call this on every button selection
def test(filepath, ignore):
# maya will send "test(name, False)"; we just ignore the 'False'
print "Here's where I would reload", filepath
example = cmds.window(title = 'example')
menubar = cmds.menuBarLayout()
for name in folder_names:
menuname = name
if menuname:
menuname = menuname.split("/")[-2] # we used trailing slashes
else:
menuname = "root"
cmds.menu(label = menuname)
file_names = root_dict[name]
file_names.sort()
for fn in file_names:
mi = cmds.menuItem(label = fn, command = partial(test, fn))
cmds.setParent(menubar)