Directory tree generator. This behaves exactly like walk(), except that it yields a 4-tuple dirpath, dirnames, filenames, dirfd `dirpath`, `dirnames` and `filenames` are identical to walk() output, and `dirfd` is a file descriptor referring to the directory `di
(top=".", topdown=True, onerror=None, *, follow_symlinks=False, dir_fd=None)
| 450 | if {open, stat} <= supports_dir_fd and {scandir, stat} <= supports_fd: |
| 451 | |
| 452 | def fwalk(top=".", topdown=True, onerror=None, *, follow_symlinks=False, dir_fd=None): |
| 453 | """Directory tree generator. |
| 454 | |
| 455 | This behaves exactly like walk(), except that it yields a 4-tuple |
| 456 | |
| 457 | dirpath, dirnames, filenames, dirfd |
| 458 | |
| 459 | `dirpath`, `dirnames` and `filenames` are identical to walk() output, |
| 460 | and `dirfd` is a file descriptor referring to the directory `dirpath`. |
| 461 | |
| 462 | The advantage of fwalk() over walk() is that it's safe against symlink |
| 463 | races (when follow_symlinks is False). |
| 464 | |
| 465 | If dir_fd is not None, it should be a file descriptor open to a directory, |
| 466 | and top should be relative; top will then be relative to that directory. |
| 467 | (dir_fd is always supported for fwalk.) |
| 468 | |
| 469 | Caution: |
| 470 | Since fwalk() yields file descriptors, those are only valid until the |
| 471 | next iteration step, so you should dup() them if you want to keep them |
| 472 | for a longer period. |
| 473 | |
| 474 | Example: |
| 475 | |
| 476 | import os |
| 477 | for root, dirs, files, rootfd in os.fwalk('python/Lib/xml'): |
| 478 | print(root, "consumes", end="") |
| 479 | print(sum(os.stat(name, dir_fd=rootfd).st_size for name in files), |
| 480 | end="") |
| 481 | print("bytes in", len(files), "non-directory files") |
| 482 | if '__pycache__' in dirs: |
| 483 | dirs.remove('__pycache__') # don't visit __pycache__ directories |
| 484 | """ |
| 485 | sys.audit("os.fwalk", top, topdown, onerror, follow_symlinks, dir_fd) |
| 486 | top = fspath(top) |
| 487 | stack = [(_fwalk_walk, (True, dir_fd, top, top, None))] |
| 488 | isbytes = isinstance(top, bytes) |
| 489 | try: |
| 490 | while stack: |
| 491 | yield from _fwalk(stack, isbytes, topdown, onerror, follow_symlinks) |
| 492 | finally: |
| 493 | # Close any file descriptors still on the stack. |
| 494 | while stack: |
| 495 | action, value = stack.pop() |
| 496 | if action == _fwalk_close: |
| 497 | close(value) |
| 498 | |
| 499 | # Each item in the _fwalk() stack is a pair (action, args). |
| 500 | _fwalk_walk = 0 # args: (isroot, dirfd, toppath, topname, entry) |