diff options
author | Stanislav Zmiev <zertarx@gmail.com> | 2022-07-22 23:55:46 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-07-22 23:55:46 (GMT) |
commit | c1e929858ad96fc6e41bc637e5ec9343b4f7e3c7 (patch) | |
tree | 29ed6ea80acdbb4b670282f391adaac75fea1a38 /Doc/library/pathlib.rst | |
parent | e4d3a96a113070fde433834a6c9fb79ebeebad4a (diff) | |
download | cpython-c1e929858ad96fc6e41bc637e5ec9343b4f7e3c7.zip cpython-c1e929858ad96fc6e41bc637e5ec9343b4f7e3c7.tar.gz cpython-c1e929858ad96fc6e41bc637e5ec9343b4f7e3c7.tar.bz2 |
gh-90385: Add `pathlib.Path.walk()` method (GH-92517)
Automerge-Triggered-By: GH:brettcannon
Diffstat (limited to 'Doc/library/pathlib.rst')
-rw-r--r-- | Doc/library/pathlib.rst | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst index 0454918..19944bd 100644 --- a/Doc/library/pathlib.rst +++ b/Doc/library/pathlib.rst @@ -946,6 +946,101 @@ call fails (for example because the path doesn't exist). to the directory after creating the iterator, whether a path object for that file be included is unspecified. +.. method:: Path.walk(top_down=True, on_error=None, follow_symlinks=False) + + Generate the file names in a directory tree by walking the tree + either top-down or bottom-up. + + For each directory in the directory tree rooted at *self* (including + *self* but excluding '.' and '..'), the method yields a 3-tuple of + ``(dirpath, dirnames, filenames)``. + + *dirpath* is a :class:`Path` to the directory currently being walked, + *dirnames* is a list of strings for the names of subdirectories in *dirpath* + (excluding ``'.'`` and ``'..'``), and *filenames* is a list of strings for + the names of the non-directory files in *dirpath*. To get a full path + (which begins with *self*) to a file or directory in *dirpath*, do + ``dirpath / name``. Whether or not the lists are sorted is file + system-dependent. + + If the optional argument *top_down* is true (which is the default), the triple for a + directory is generated before the triples for any of its subdirectories + (directories are walked top-down). If *top_down* is false, the triple + for a directory is generated after the triples for all of its subdirectories + (directories are walked bottom-up). No matter the value of *top_down*, the + list of subdirectories is retrieved before the triples for the directory and + its subdirectories are walked. + + When *top_down* is true, the caller can modify the *dirnames* list in-place + (for example, using :keyword:`del` or slice assignment), and :meth:`Path.walk` + will only recurse into the subdirectories whose names remain in *dirnames*. + This can be used to prune the search, or to impose a specific order of visiting, + or even to inform :meth:`Path.walk` about directories the caller creates or + renames before it resumes :meth:`Path.walk` again. Modifying *dirnames* when + *top_down* is false has no effect on the behavior of :meth:`Path.walk()` since the + directories in *dirnames* have already been generated by the time *dirnames* + is yielded to the caller. + + By default, errors from :func:`os.scandir` are ignored. If the optional + argument *on_error* is specified, it should be a callable; it will be + called with one argument, an :exc:`OSError` instance. The callable can handle the + error to continue the walk or re-raise it to stop the walk. Note that the + filename is available as the ``filename`` attribute of the exception object. + + By default, :meth:`Path.walk` does not follow symbolic links, and instead adds them + to the *filenames* list. Set *follow_symlinks* to true to resolve symlinks + and place them in *dirnames* and *filenames* as appropriate for their targets, and + consequently visit directories pointed to by symlinks (where supported). + + .. note:: + + Be aware that setting *follow_symlinks* to true can lead to infinite + recursion if a link points to a parent directory of itself. :meth:`Path.walk` + does not keep track of the directories it has already visited. + + .. note:: + :meth:`Path.walk` assumes the directories it walks are not modified during + execution. For example, if a directory from *dirnames* has been replaced + with a symlink and *follow_symlinks* is false, :meth:`Path.walk` will + still try to descend into it. To prevent such behavior, remove directories + from *dirnames* as appropriate. + + .. note:: + + Unlike :func:`os.walk`, :meth:`Path.walk` lists symlinks to directories in + *filenames* if *follow_symlinks* is false. + + This example displays the number of bytes used by all files in each directory, + while ignoring ``__pycache__`` directories:: + + from pathlib import Path + for root, dirs, files in Path("cpython/Lib/concurrent").walk(on_error=print): + print( + root, + "consumes", + sum((root / file).stat().st_size for file in files), + "bytes in", + len(files), + "non-directory files" + ) + if '__pycache__' in dirs: + dirs.remove('__pycache__') + + This next example is a simple implementation of :func:`shutil.rmtree`. + Walking the tree bottom-up is essential as :func:`rmdir` doesn't allow + deleting a directory before it is empty:: + + # Delete everything reachable from the directory "top". + # CAUTION: This is dangerous! For example, if top == Path('/'), + # it could delete all of your files. + for root, dirs, files in top.walk(topdown=False): + for name in files: + (root / name).unlink() + for name in dirs: + (root / name).rmdir() + + .. versionadded:: 3.12 + .. method:: Path.lchmod(mode) Like :meth:`Path.chmod` but, if the path points to a symbolic link, the @@ -1285,6 +1380,7 @@ Below is a table mapping various :mod:`os` functions to their corresponding :func:`os.path.expanduser` :meth:`Path.expanduser` and :meth:`Path.home` :func:`os.listdir` :meth:`Path.iterdir` +:func:`os.walk` :meth:`Path.walk` :func:`os.path.isdir` :meth:`Path.is_dir` :func:`os.path.isfile` :meth:`Path.is_file` :func:`os.path.islink` :meth:`Path.is_symlink` |