0

I am writing a method that takes a filename and a path to a directory and returns the next available filename in the directory or None if there are no files with names that would sort after the file.

There are plenty of questions about how to list all the files in a directory or iterate over them, but I am not sure if the best solution to finding a single next filename is to use the list that one of the previous answers generated and then find the location of the current file in the list and choose the next element (or None if we're already on the last one).


EDIT: here's my current file-picking code. It's reused from a different part of the project, where it is used to pick a random image from a potentially nested series of directories.

# picks a file from a directory
# if the file is also a directory, pick a file from the new directory
# this might choke up if it encounters a directory only containing invalid files
def pickNestedFile(directory, bad_files):
    file=None
    while file is None or file in bad_files:
        file=random.choice(os.listdir(directory))
    #file=directory+file # use the full path name
    print "Trying "+file
    if os.path.isdir(os.path.join(directory, file))==True:
        print "It's a directory!"
        return pickNestedFile(directory+"/"+file, bad_files)
    else:
        return directory+"/"+file

The program I am using this in now is to take a folder of chatlogs, pick a random log, starting position, and length. These will then be processed into a MOTD-like series of (typically) short log snippets. What I need the next-file picking ability for is when the length is unusually long or the starting line is at the end of the file, so that it continues at the top of the next file (a.k.a. wrap around midnight).

I am open to the idea of using a different method to choose the file, since the above method does not discreetly give a separate filename and directory and I'd have to go use a listdir and match to get an index anyway.

Community
  • 1
  • 1
cjm
  • 451
  • 4
  • 20
  • 3
    How do you define *"next available filename"*? – UnholySheep Mar 16 '17 at 19:11
  • @UnholySheep Specifically, I'm processing chatlogs. I'd assume a standard alphanumeric sorting would work just fine, unless you're they type of person to use emoji in your log names. – cjm Mar 16 '17 at 19:26

2 Answers2

1

You should probably consider rewriting your program to not have to use this. But this would be how you could do it:

import os

def nextFile(filename,directory):
    fileList = os.listdir(directory)
    nextIndex = fileList.index(filename) + 1
    if nextIndex == 0 or nextIndex == len(fileList):
        return None
    return fileList[nextIndex]

print(nextFile("mail","test"))
Neil
  • 14,063
  • 3
  • 30
  • 51
  • Would a better structure be to create a list of files in the directory and pick an index to start at and increment the index to get the next file when necessary? – cjm Mar 16 '17 at 19:23
  • You could also just for loop through the array that's returned from `os.listdir()`. – Neil Mar 16 '17 at 19:25
  • However, if you prefer this method, it's your code. If you could mark as solution and upvote, that would help a lot. You can also sort os.path(), too. So, you can enforce alphabetical order. – Neil Mar 16 '17 at 19:27
  • I edited my question to include my existing code and reasoning for asking the question I asked. With that in mind, would picking an index from os.listdir() for my initial file and then incrementing that index if necessary be a better solution? – cjm Mar 16 '17 at 19:51
0

I tweaked the accepted answer to allow new files to be added to the directory on the fly and for it to work if a file is deleted or changed or doesn't exist. There are better ways to work with filenames/paths, but the example below keeps it simple. Maybe it's helpful:

import os
def next_file_in_dir(directory, current_file=None):
    file_list = os.listdir(directory)
    next_index = 0
    if current_file in file_list:
        next_index = file_list.index(current_file) + 1
    if next_index >= len(file_list):
        next_index = 0
    return file_list[next_index]

file_name = None
directory = "videos"
user_advanced_to_next = True
while user_advanced_to_next:
    file_name = next_file_in_dir(directory=directory, current_file=file_name )
    user_advanced_to_next = play_video("{}/{}".format(directory, file_name))
finish_and_clean_up()
JayCrossler
  • 2,079
  • 2
  • 22
  • 22