19

I use pathlib.Path().iterdir() to get sub-dictionary of the path.

Under /home/yuanyi/workspace/app, there are 4 folders: 01, 02, 03, 04.

from pathlib import Path
for subdir in Path('/home/yuanyi/workspace/app').iterdir():
    print(subdir)

But the result is not ordered.

/home/yuanyi/workspace/app/02
/home/yuanyi/workspace/app/03
/home/yuanyi/workspace/app/01
/home/yuanyi/workspace/app/00

Wht the result is not the following:

/home/yuanyi/workspace/app/01
/home/yuanyi/workspace/app/02
/home/yuanyi/workspace/app/03
/home/yuanyi/workspace/app/04

I want to know how the iterator works, and what's the best method to get ordered result.

djvg
  • 11,722
  • 5
  • 72
  • 103
wuyuanyi
  • 339
  • 1
  • 2
  • 8
  • 1
    Out of interest, what OS are you using? – Ray Jan 24 '18 at 18:16
  • 1
    From the [Path.iterdir() docs](https://docs.python.org/3/library/pathlib.html#pathlib.Path.iterdir): "The children are yielded in arbitrary order, ..." – djvg Sep 07 '21 at 11:16

2 Answers2

27

You can use "sorted()"

Built-in Functions Python - sorted()

from pathlib import Path
for subdir in sorted(Path('/some/path').iterdir()):
    print(subdir)

NOTE: @NamitJuneja points out, This changes iterating over a generator to iterating over a list. Hence if there are a huge number of files in the memory, loading them all into the memory (by loading them into a list) might cause problems.

On my Mac, the iterdir() method returns the list already sorted. So that looks system dependent. What OS are you using?

Tim Grant
  • 3,300
  • 4
  • 23
  • 31
  • 3
    This changes iterating over a generator to iterating over a list. Hence if there are a huge number of files in the memory, loading them all into the memory (by loading them into a list) might cause problems – Namit Juneja Feb 23 '20 at 04:27
  • Thanks, @NamitJuneja, I've incorporated your comment into the answer. Edit as you see fit! – Tim Grant Feb 23 '20 at 12:30
3

Think you should figure out the result from this,

>>> l = ['/home/yuanyi/workspace/app/02',
'/home/yuanyi/workspace/app/03', '/home/yuanyi/workspace/app/01']
>>> for i in sorted(l, key=lambda m: int(m.split('/')[-1])):
    print i


/home/yuanyi/workspace/app/01
/home/yuanyi/workspace/app/02
/home/yuanyi/workspace/app/03
>>> 

or

for i in sorted(l, key=lambda m: int(m.split(os.sep)[-1])):
    print i
Avinash Raj
  • 172,303
  • 28
  • 230
  • 274
  • Well, do you means I need to do some works else to sort the order? Is there any methods of iterator to get ordered result? – wuyuanyi Mar 16 '16 at 11:14
  • Very nice try, but only `os.walk()` guarantees [top-down ordering](https://docs.python.org/3/library/os.html#os.walk). I believe this is a small example but that's likely what the poster expects. Unfortunately, none of the `Pathlib` variants provide this guarantee so the user must implement their own sort. How to do top-down sort? – ingyhere Apr 29 '20 at 02:56
  • 1
    Ahh, yes, I found the answer by sifting through [Python source](https://github.com/python/): So `iterdir()` uses `listdir()` and `glob()` uses `scandir()`. Scandir is picked up from the `os` module. Since `os.walk()` also uses `scandir()`, it looks like the closest thing to `os.walk()` is `pathlib.glob()` but I'm not sure how that could be used to make it look like `os.walk()` output (the art). If you're wondering why some parts of Pathlib use `listdir()` it was a [ruling by Guido](https://mail.python.org/pipermail/python-dev/2013-November/130583.html). – ingyhere Apr 29 '20 at 03:20