1

I want to find the first filename myfile????.txt that doesn't exist yet (???? is a number). This works:

import os
i = 0
f = 'myfile%04i.txt' % i
while os.path.exists(f):
    i += 1
    f = 'myfile%04i.txt' % i

but I don't like the code duplication of f = ....

Is there a pythonic way to avoid the code duplication in this while loop?

NB: I have posted a half-satisfactory solution, using a do/while idiom, as mentioned in the main answer of Emulate a do-while loop in Python?, but I still wonder if there is better way for this particular case (thus, it's not a dupe of this question).

Basj
  • 41,386
  • 99
  • 383
  • 673

5 Answers5

6

You do not need to follow the while paradiagm here, a nested generator expression with next() works:

import os
from itertools import count
f = next(f for f in ('myfile%04i.txt' % i for i in count()) if not os.path.exists(f))
print(f)
Chris_Rands
  • 38,994
  • 14
  • 83
  • 119
  • Perfect solution (I just edited so that we can easily test it by copying/pasting). – Basj Nov 27 '18 at 14:46
  • @Basj ok, note I just edited it a bit to correct a mistake (of mine) – Chris_Rands Nov 27 '18 at 14:47
  • 1
    This is really pythonic, concise, and explicit! I thought it would be possible with a generator / next() but I didn't find how to do it, thanks a lot! – Basj Nov 27 '18 at 14:49
3

Get rid of the f variable.

import os

i = 0
while os.path.exists('myfile%04i.txt' % i):
    i += 1
Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
  • Oh great! But I still need `f` at the end, is there a way to get it? – Basj Nov 27 '18 at 14:36
  • Make `f` a variable and "give" it to `while`. – Ctrl S Nov 27 '18 at 14:37
  • @Basj Yes, you could still initialize `f` before the loop, then use `while os.path.exists(f % i)` – Bill the Lizard Nov 27 '18 at 14:39
  • 2
    The second solution doesn't work, if you `print f`, you'll get `myfile%04i.txt` and not `myfile0002.txt` for example. So we would need to add `f = f % i` at the end to really get the answer in `f`. It's probably the best solution so far though! – Basj Nov 27 '18 at 14:43
  • Ah, you're right. My bad for not running it. I'm going to revert my edit, since that's essentially what you started with. – Bill the Lizard Nov 27 '18 at 14:47
0

I nearly found the answer while writing the end of the question. After a few modifications, it works:

import os
i = 0
while True:
    f = 'myfile%04i.txt' % i
    if not os.path.exists(f):
        break
    i += 1
print f

Still I wonder if there is a more pythonic way, maybe with an iterator, generator, next(...) or anything like this.

Basj
  • 41,386
  • 99
  • 383
  • 673
0

Is this too simple?

import os
f = 'myfile0000.txt'
while os.path.exists(f):
    i += 1
    f = 'myfile%04i.txt' % i
Dominique
  • 16,450
  • 15
  • 56
  • 112
  • It "works", like my question's code, and the solution I posted, but I wanted to know if there is a solution without duplication of `f = ...`. – Basj Nov 27 '18 at 14:41
0

You could do:

import os
from itertools import count

cursor = count()
it = iter((path for path in map(lambda x: 'myfile%04i.txt' % x, cursor) if not os.path.exists(path)))
first = next(it, None)

if first:
    print(first)

Output

myfile0000.txt
Dani Mesejo
  • 61,499
  • 6
  • 49
  • 76