Skip to content

shutil.rmtree() on a symlink with a trailing slash empties its target #160322

Closed

Description

@gpshead

Bug report

Bug description:

shutil.rmtree() is documented to refuse a symbolic link to a directory, but the check is an lstat() of the path as given, so a trailing separator gets past it. rmtree('link/') deletes everything inside the link's target and then fails in the final rmdir(). The original symptom was fixed for the plain spelling in gh-46010.

import os, shutil, tempfile

tmp = tempfile.mkdtemp()
target = os.path.join(tmp, 'target')
os.mkdir(target)
open(os.path.join(target, 'file'), 'w').close()
link = os.path.join(tmp, 'link')
os.symlink(target, link)

for path in link, link + os.sep:
    try:
        shutil.rmtree(path)
    except OSError as exc:
        print(f'{type(exc).__name__}: {exc.strerror}')
    print(os.listdir(target))

Output:

OSError: None
['file']
NotADirectoryError: Not a directory
[]

The second call should fail with "Cannot call rmtree on a symbolic link" like the first and leave target alone.

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Linked PRs

Activity

  1. self-assigned this
    on Oct 22, 2026
  2. added
    type-bugAn unexpected behavior, bug, or error
    stdlibStandard Library Python modules in the Lib/ directory
    on Oct 22, 2026
  3. added 2 commits that reference this issue on Oct 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

stdlibStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or error

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions