2

I am trying to write a function that assigns a path name and filename to a variable that is based on a name of a file than exists in the folder. Then, if the name of the file already exists the file name is auto-incremented. I have seen some posts on this using while loop but I cannot get my head around this and would like to wrap it in a recursive function.

Here is what I have so far. When testing with print statement every works well. But it does not return the new name back to the main program.

def checkfile(ii, new_name,old_name):

    if not os.path.exists(new_name):
        return new_name

    if os.path.exists(new_name):
        ii+=1
        new_name = os.path.join(os.path.split(old_name)[0],str(ii) + 'snap_'+ os.path.split(old_name)[1])
        print new_name

    old_name = “D:\Bar\foo”
    new_name= os.path.join(os.path.split(old_name)[0],”output_” + os.path.split(old_name)[1])
    checkfile(0,new_name,old_name)
3
  • Is your goal just to ensure you have a unique file name? Because there are easier ways to do that... Commented Apr 16, 2015 at 18:33
  • @1.618 I don't think the goal is for a unique name, but rather to automatically append an incrementing index if you try to save the same file twice (similar to what most OS's do if you do so via the finder/browser) Commented Apr 16, 2015 at 19:03
  • It does not return because you forgot return statements. ;) Commented Apr 16, 2015 at 20:47

1 Answer 1

6

While I wouldn't recommend using recursion for this (python's stack maxes out at about 1000 function calls deep), you're just missing a return for the recursive bit:

new_name= os.path.join(os.path.split(old_name)[0],”output_” + os.path.split(old_name)[1])
checkfile(0,new_name,old_name)

Should instead be:

new_name= os.path.join(os.path.split(old_name)[0],”output_” + os.path.split(old_name)[1])
return checkfile(ii,new_name,old_name)

But really, you can make this a whole lot simpler by re-writing it as:

 def checkfile(path):
     path      = os.path.expanduser(path)

     if not os.path.exists(path):
        return path

     root, ext = os.path.splitext(os.path.expanduser(path))
     dir       = os.path.dirname(root)
     fname     = os.path.basename(root)
     candidate = fname+ext
     index     = 0
     ls        = set(os.listdir(dir))
     while candidate in ls:
             candidate = "{}_{}{}".format(fname,index,ext)
             index    += 1
     return os.path.join(dir,candidate)

This form also handles the fact that filenames have extensions, which your original code doesn't, at least not very clearly. It also avoids needless os.path.exist's, which can be very expensive, especially if the path is a network location.

Sign up to request clarification or add additional context in comments.

1 Comment

Many thanks ! Both solutions work perfectly of course. I appreciate your re-write is much more efficient.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.