{"id":20200,"date":"2022-03-11T16:36:47","date_gmt":"2022-03-11T11:06:47","guid":{"rendered":"http:\/\/www.pythonpool.com\/?p=20200"},"modified":"2026-07-13T12:38:58","modified_gmt":"2026-07-13T07:08:58","slug":"python-shutil-rmtree","status":"publish","type":"post","link":"https:\/\/www.pythonpool.com\/python-shutil-rmtree\/","title":{"rendered":"shutil.rmtree(): Delete a Directory Tree Safely"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_85 counter-hierarchy ez-toc-counter ez-toc-transparent ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Contents<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #990303;color:#990303\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #990303;color:#990303\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 eztoc-toggle-hide-by-default' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/www.pythonpool.com\/python-shutil-rmtree\/#Quick_Answer\" >Quick Answer<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/www.pythonpool.com\/python-shutil-rmtree\/#Remove_A_Temporary_Directory_Tree\" >Remove A Temporary Directory Tree<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/www.pythonpool.com\/python-shutil-rmtree\/#Check_The_Path_First\" >Check The Path First<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/www.pythonpool.com\/python-shutil-rmtree\/#Preview_Files_Before_Removal\" >Preview Files Before Removal<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/www.pythonpool.com\/python-shutil-rmtree\/#Handle_Missing_Paths\" >Handle Missing Paths<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/www.pythonpool.com\/python-shutil-rmtree\/#Fix_Read-Only_File_Problems\" >Fix Read-Only File Problems<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/www.pythonpool.com\/python-shutil-rmtree\/#Create_A_Safer_Helper\" >Create A Safer Helper<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/www.pythonpool.com\/python-shutil-rmtree\/#Validate_and_Preview_the_Target\" >Validate and Preview the Target<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/www.pythonpool.com\/python-shutil-rmtree\/#Handle_Read-Only_Files_With_onexc\" >Handle Read-Only Files With onexc<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/www.pythonpool.com\/python-shutil-rmtree\/#Frequently_Asked_Questions\" >Frequently Asked Questions<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/www.pythonpool.com\/python-shutil-rmtree\/#What_does_shutilrmtree_do\" >What does shutil.rmtree() do?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/www.pythonpool.com\/python-shutil-rmtree\/#How_do_I_delete_a_directory_only_if_it_is_safe\" >How do I delete a directory only if it is safe?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/www.pythonpool.com\/python-shutil-rmtree\/#How_do_I_remove_read-only_files_with_rmtree\" >How do I remove read-only files with rmtree()?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-14\" href=\"https:\/\/www.pythonpool.com\/python-shutil-rmtree\/#Should_I_use_ignore_errorsTrue_with_shutilrmtree\" >Should I use ignore_errors=True with shutil.rmtree()?<\/a><\/li><\/ul><\/li><\/ul><\/nav><\/div>\n<h2><span class=\"ez-toc-section\" id=\"Quick_Answer\"><\/span>Quick Answer<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Call <code>shutil.rmtree(path)<\/code> to delete a directory and everything below it. Validate that the resolved path is the intended directory, reject symlinks or paths outside an allowed root, and do not pass unchecked user input. Use <code>onexc<\/code> when you need a recovery callback for errors such as read-only files.<\/p>\n<figure class=\"pythonpool-article-visual\"><img src=\"https:\/\/www.pythonpool.com\/wp-content\/uploads\/2026\/07\/shutil-rmtree-safe.png\" alt=\"Safe Python shutil.rmtree directory deletion flow with path checks and error handling\" width=\"1600\" height=\"1066\" loading=\"lazy\" decoding=\"async\"><figcaption>Validate the directory, preview its contents, remove the tree, and handle read-only or permission errors deliberately.<\/figcaption><\/figure>\n<p><code>shutil.rmtree()<\/code> removes an entire directory tree in Python. That includes the target folder, every nested subfolder, and every file inside it, so the function should be used with clear path checks.<\/p>\n<p>The main reference is the Python documentation for <a href=\"https:\/\/docs.python.org\/3\/library\/shutil.html#shutil.rmtree\">shutil.rmtree()<\/a>. Related standard-library docs cover <a href=\"https:\/\/docs.python.org\/3\/library\/pathlib.html\">pathlib<\/a> and <a href=\"https:\/\/docs.python.org\/3\/library\/tempfile.html\">tempfile<\/a>.<\/p>\n<p>Use <code>rmtree()<\/code> for generated folders such as build output, temporary workspaces, extracted archives, cache folders, and test directories. Do not point it at user data unless the user has clearly requested that removal and the path has been checked.<\/p>\n<p>A good cleanup script should be boring and explicit. It should name the base directory, build the target path from known pieces, print or log what it is about to remove, and fail loudly when the target is not the expected kind of path.<\/p>\n<p>That extra caution matters in scheduled jobs and CI pipelines because a typo can run unattended. A few path checks are cheaper than recovering accidentally removed project output or user files.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Remove_A_Temporary_Directory_Tree\"><\/span>Remove A Temporary Directory Tree<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>The safest way to learn <code>rmtree()<\/code> is to create a temporary folder, put files inside it, and remove that test tree.<\/p>\n<pre><code class=\"language-python\">from pathlib import Path\nimport shutil\nimport tempfile\n\nbase = Path(tempfile.mkdtemp())\ntarget = base \/ \"demo-tree\"\n\n(target \/ \"logs\").mkdir(parents=True)\n(target \/ \"logs\" \/ \"app.log\").write_text(\"hello\\n\")\n(target \/ \"notes.txt\").write_text(\"temporary note\\n\")\n\nprint(target.exists())\nshutil.rmtree(target)\nprint(target.exists())\n\nshutil.rmtree(base)\n<\/code><\/pre>\n<p>This example avoids touching a real project folder. It also shows the key behavior: after <code>rmtree()<\/code> runs, the target directory no longer exists.<\/p>\n<p>Unlike <code>Path.unlink()<\/code>, which removes one file, <code>rmtree()<\/code> is built for nested directories.<\/p>\n<p>Use temporary directories for examples, tests, and experiments. They let you verify behavior on your machine without risking files that belong to a real project.<\/p>\n<p><!-- Python Pool visual layout repair 2026-07-13 --><\/p>\n<figure class=\"pythonpool-article-visual pythonpool-supporting-visual\"><img src=\"https:\/\/www.pythonpool.com\/wp-content\/uploads\/2026\/07\/rmtree-tree-b211.png\" alt=\"Python Pool infographic showing a directory tree, shutil.rmtree, recursive deletion, and empty path\" width=\"1536\" height=\"1054\" loading=\"lazy\" decoding=\"async\"><figcaption>shutil.rmtree recursively removes a directory tree and its contents.<\/figcaption><\/figure>\n<h2><span class=\"ez-toc-section\" id=\"Check_The_Path_First\"><\/span>Check The Path First<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Before removing anything, confirm that the path exists, is a directory, and points to the area you expected.<\/p>\n<pre><code class=\"language-python\">from pathlib import Path\nimport shutil\n\nproject_root = Path.cwd().resolve()\ntarget = (project_root \/ \"build\" \/ \"cache\").resolve()\n\nif not target.exists():\n    print(\"Nothing to remove\")\nelif not target.is_dir():\n    raise NotADirectoryError(target)\nelif project_root not in target.parents:\n    raise ValueError(f\"Refusing to remove outside project: {target}\")\nelse:\n    shutil.rmtree(target)\n    print(f\"Removed {target}\")\n<\/code><\/pre>\n<p>The parent check protects against deleting a folder outside the intended project. This is especially important when a path comes from a command-line argument, config file, or job input.<\/p>\n<p>Resolve paths before comparing them so relative parts like <code>..<\/code> do not hide the real target.<\/p>\n<p>For command-line tools, accept a relative path under a configured workspace instead of accepting any absolute path. That keeps the cleanup boundary small and easy to review.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Preview_Files_Before_Removal\"><\/span>Preview Files Before Removal<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>A preview step is useful for scripts that clean generated folders. It gives you a chance to print the first few paths before removal.<\/p>\n<pre><code class=\"language-python\">from pathlib import Path\n\ntarget = Path(\"build\").resolve()\n\nif target.is_dir():\n    contents = sorted(path.relative_to(target) for path in target.rglob(\"*\"))\n    for path in contents[:10]:\n        print(path)\n    print(f\"Total entries: {len(contents)}\")\nelse:\n    print(\"Target directory is missing\")\n<\/code><\/pre>\n<p>For automated cleanup, you might log the count and target path. For interactive cleanup, ask for confirmation after showing the preview.<\/p>\n<p>A preview is not a substitute for path guards, but it makes mistakes easier to spot before the final call.<\/p>\n<p>For large folders, avoid printing every entry. A short sample and a total count are usually enough to confirm that the script is looking at the right tree.<\/p>\n<figure class=\"pythonpool-article-visual pythonpool-supporting-visual\"><img src=\"https:\/\/www.pythonpool.com\/wp-content\/uploads\/2026\/07\/rmtree-guard-b211.png\" alt=\"Python Pool infographic mapping a path through validation, allowlist, confirmation, and deletion\" width=\"1536\" height=\"1054\" loading=\"lazy\" decoding=\"async\"><figcaption>Recursive deletion needs strict path validation and a clear safety boundary.<\/figcaption><\/figure>\n<h2><span class=\"ez-toc-section\" id=\"Handle_Missing_Paths\"><\/span>Handle Missing Paths<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>If a folder may already be gone, check first or use <code>ignore_errors=True<\/code> only when you genuinely do not care about failures.<\/p>\n<pre><code class=\"language-python\">from pathlib import Path\nimport shutil\n\ntarget = Path(\"cache\").resolve()\n\nif target.exists():\n    shutil.rmtree(target)\n    print(\"cache removed\")\nelse:\n    print(\"cache was already absent\")\n<\/code><\/pre>\n<p>This explicit form is usually clearer than suppressing every error. It distinguishes a missing folder from permission problems, locked files, and incorrect path types.<\/p>\n<p>Use <code>ignore_errors=True<\/code> for best-effort cleanup in short-lived temporary directories, not for important maintenance scripts.<\/p>\n<p>If cleanup is part of a larger workflow, report whether anything was removed. That makes logs easier to read when a previous step skipped folder creation.<\/p>\n<figure class=\"pythonpool-article-visual pythonpool-supporting-visual\"><img src=\"https:\/\/www.pythonpool.com\/wp-content\/uploads\/2026\/07\/rmtree-errors-b211.png\" alt=\"Python Pool infographic comparing missing paths, onerror callback, permissions, and cleanup\" width=\"1536\" height=\"1054\" loading=\"lazy\" decoding=\"async\"><figcaption>Handle missing paths and permission failures deliberately rather than hiding deletion errors.<\/figcaption><\/figure>\n<h2><span class=\"ez-toc-section\" id=\"Fix_Read-Only_File_Problems\"><\/span>Fix Read-Only File Problems<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>On some systems, read-only files can block removal. Python supports an <code>onexc<\/code> callback for handling errors during traversal.<\/p>\n<pre><code class=\"language-python\">from pathlib import Path\nimport os\nimport shutil\nimport stat\n\ndef make_writable(function, path, excinfo):\n    current = Path(path)\n    current.chmod(current.stat().st_mode | stat.S_IWRITE)\n    function(path)\n\ntarget = Path(\"readonly-cache\")\nif target.exists():\n    shutil.rmtree(target, onexc=make_writable)\n\nprint(\"cleanup attempted\")\n<\/code><\/pre>\n<p>Keep callbacks narrow. In this case the callback only makes a blocked path writable and retries the failing operation.<\/p>\n<p>If permission errors keep happening, log the path and stop. Repeated retries can make troubleshooting harder and may hide a real access problem.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Create_A_Safer_Helper\"><\/span>Create A Safer Helper<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>For repeated cleanup tasks, wrap <code>rmtree()<\/code> in a helper that accepts only paths under a known workspace.<\/p>\n<pre><code class=\"language-python\">from pathlib import Path\nimport shutil\n\ndef remove_tree_under(base_dir, relative_path):\n    base = Path(base_dir).resolve()\n    target = (base \/ relative_path).resolve()\n\n    if base == target or base not in target.parents:\n        raise ValueError(f\"Unsafe removal target: {target}\")\n    if not target.exists():\n        return False\n    if not target.is_dir():\n        raise NotADirectoryError(target)\n\n    shutil.rmtree(target)\n    return True\n\nremoved = remove_tree_under(Path.cwd(), \"build\/cache\")\nprint(removed)\n<\/code><\/pre>\n<p>This pattern works well for deleting build folders, cache folders, and generated test output because the allowed base directory is explicit.<\/p>\n<p>The practical rule is to treat <code>shutil.rmtree()<\/code> as a powerful cleanup tool: use it for directory trees, test with temporary folders, resolve and guard paths, preview important removals, and handle errors without hiding unexpected failures.<\/p>\n<p>When a task only needs to remove one file, use <code>Path.unlink()<\/code>. When a task needs to remove an empty folder, use <code>Path.rmdir()<\/code>. Save <code>rmtree()<\/code> for full directory trees.<\/p>\n<figure class=\"pythonpool-article-visual pythonpool-supporting-visual\"><img src=\"https:\/\/www.pythonpool.com\/wp-content\/uploads\/2026\/07\/rmtree-check-b211.png\" alt=\"Python Pool infographic testing symlinks, race conditions, backups, dry runs, and validation\" width=\"1536\" height=\"1054\" loading=\"lazy\" decoding=\"async\"><figcaption>Check symlink behavior, races, backups, dry-run policy, permissions, and irreversible impact.<\/figcaption><\/figure>\n<h2><span class=\"ez-toc-section\" id=\"Validate_and_Preview_the_Target\"><\/span>Validate and Preview the Target<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p><code>rmtree()<\/code> is recursive and irreversible. Resolve the target, check that it is a directory, keep it inside an allowed project root, and preview entries before removal.<\/p>\n<pre><code class=\"language-python\">from pathlib import Path\nimport shutil\n\nroot = Path.cwd().resolve()\ntarget = (root \/ \"build\" \/ \"cache\").resolve()\nif not target.is_dir() or target.is_symlink():\n    raise ValueError(\"refusing to remove this target\")\nif root not in target.parents:\n    raise ValueError(\"target is outside the project root\")\nprint([p.name for p in target.iterdir()])\n# Call shutil.rmtree(target) only after an explicit confirmation.\n<\/code><\/pre>\n<p>Never infer permission to delete from a filename alone. A path such as <code>build<\/code> can resolve somewhere unexpected when the process working directory changes.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Handle_Read-Only_Files_With_onexc\"><\/span>Handle Read-Only Files With onexc<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>On Windows, a tree can contain files with a read-only attribute. An <code>onexc<\/code> callback can clear that attribute and retry the operation, while other failures should still propagate so the caller knows cleanup was incomplete.<\/p>\n<pre><code class=\"language-python\">import os\nimport shutil\nimport stat\n\ndef remove_readonly(function, path, exc):\n    os.chmod(path, stat.S_IWRITE)\n    function(path)\n\nshutil.rmtree(\"temporary-tree\", onexc=remove_readonly)\n<\/code><\/pre>\n<p>For untrusted paths or security-sensitive cleanup, use an allow-list and consider a dedicated sandbox. Do not set <code>ignore_errors=True<\/code> when silent partial deletion would be dangerous.<\/p>\n<p data-pythonpool-link-set=\"2026-07-13-priority\">Before removing a directory, compare safe file copying and checking whether a path exists. Read <a href=\"https:\/\/www.pythonpool.com\/python-copy-file\/\">python copy file<\/a> and <a href=\"https:\/\/www.pythonpool.com\/python-check-if-file-exists\/\">python check if file exists<\/a> for the related workflow.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Frequently_Asked_Questions\"><\/span>Frequently Asked Questions<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<h3><span class=\"ez-toc-section\" id=\"What_does_shutilrmtree_do\"><\/span>What does shutil.rmtree() do?<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>It recursively deletes a directory and the files and subdirectories below it. The operation is destructive and should be preceded by path validation.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"How_do_I_delete_a_directory_only_if_it_is_safe\"><\/span>How do I delete a directory only if it is safe?<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Resolve the path, verify it is the intended directory, reject symlinks, keep it under an allowed root, and preview its contents before calling rmtree().<\/p>\n<h3><span class=\"ez-toc-section\" id=\"How_do_I_remove_read-only_files_with_rmtree\"><\/span>How do I remove read-only files with rmtree()?<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Use an onexc callback that changes the file permissions and retries the failed operation, while allowing unrelated errors to propagate.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Should_I_use_ignore_errorsTrue_with_shutilrmtree\"><\/span>Should I use ignore_errors=True with shutil.rmtree()?<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Only when silent partial cleanup is acceptable. Otherwise let errors propagate or handle them explicitly so a failed deletion is visible.<\/p>\n<p><script type=\"application\/ld+json\">{\"@context\":\"https:\/\/schema.org\",\"@type\":\"FAQPage\",\"mainEntity\":[{\"@type\":\"Question\",\"name\":\"What does shutil.rmtree() do?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"It recursively deletes a directory and the files and subdirectories below it. The operation is destructive and should be preceded by path validation.\"}},{\"@type\":\"Question\",\"name\":\"How do I delete a directory only if it is safe?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"Resolve the path, verify it is the intended directory, reject symlinks, keep it under an allowed root, and preview its contents before calling rmtree().\"}},{\"@type\":\"Question\",\"name\":\"How do I remove read-only files with rmtree()?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"Use an onexc callback that changes the file permissions and retries the failed operation, while allowing unrelated errors to propagate.\"}},{\"@type\":\"Question\",\"name\":\"Should I use ignore_errors=True with shutil.rmtree()?\",\"acceptedAnswer\":{\"@type\":\"Answer\",\"text\":\"Only when silent partial cleanup is acceptable. Otherwise let errors propagate or handle them explicitly so a failed deletion is visible.\"}}]}<\/script><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Delete a directory tree with shutil.rmtree() only after validating the target, previewing its contents, and handling cleanup errors.<\/p>\n","protected":false},"author":28,"featured_media":33784,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_mi_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[15],"tags":[4900,4901,4902,4903,4906,4904,4905],"class_list":["post-20200","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tutorials","tag-access-is-denied-error-while-using-shutil-rmtree-windows","tag-access-is-denied-shutil-rmtree","tag-shutil-rmtree-folder-not-empty","tag-shutil-rmtree-hidden-files","tag-shutil-rmtree-in-python-examples","tag-shutil-rmtree-permission-denied","tag-shutil-rmtree-in-python","infinite-scroll-item"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.1 (Yoast SEO v28.0) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>shutil.rmtree(): Delete a Directory Tree Safely<\/title>\n<meta name=\"description\" content=\"Use shutil.rmtree() to remove a Python directory tree safely, with path checks, read-only cleanup, error handling, and symlink cautions.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.pythonpool.com\/python-shutil-rmtree\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"shutil.rmtree(): Delete a Directory Tree Safely\" \/>\n<meta property=\"og:description\" content=\"Delete a directory tree with shutil.rmtree() only after validating the target, previewing its contents, and handling cleanup errors.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.pythonpool.com\/python-shutil-rmtree\/\" \/>\n<meta property=\"og:site_name\" content=\"Python Pool\" \/>\n<meta property=\"article:published_time\" content=\"2022-03-11T11:06:47+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-07-13T07:08:58+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.pythonpool.com\/wp-content\/uploads\/2026\/07\/python-shutil-rmtree-directory-delete-guide-pythonpool.png\" \/>\n<meta name=\"author\" content=\"Vishnu Venkatesh\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:title\" content=\"Python Pool\" \/>\n<meta name=\"twitter:description\" content=\"Practical Python tutorials, error fixes, code examples, and project guides.\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/www.pythonpool.com\/wp-content\/uploads\/2026\/07\/python-shutil-rmtree-directory-delete-guide-pythonpool.png\" \/>\n<meta name=\"twitter:creator\" content=\"@pythonpool\" \/>\n<meta name=\"twitter:site\" content=\"@pythonpool\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Vishnu Venkatesh\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.pythonpool.com\\\/python-shutil-rmtree\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.pythonpool.com\\\/python-shutil-rmtree\\\/\"},\"author\":{\"name\":\"Vishnu Venkatesh\",\"@id\":\"https:\\\/\\\/www.pythonpool.com\\\/#\\\/schema\\\/person\\\/5e8aa48e7557450d345c829305550688\"},\"headline\":\"shutil.rmtree(): Delete a Directory Tree Safely\",\"datePublished\":\"2022-03-11T11:06:47+00:00\",\"dateModified\":\"2026-07-13T07:08:58+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.pythonpool.com\\\/python-shutil-rmtree\\\/\"},\"wordCount\":1064,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.pythonpool.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.pythonpool.com\\\/python-shutil-rmtree\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.pythonpool.com\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/python-shutil-rmtree-directory-delete-guide-pythonpool.png\",\"keywords\":[\"access is denied error while using shutil.rmtree windows\",\"access is denied shutil.rmtree\",\"shutil rmtree folder not empty\",\"shutil rmtree hidden files\",\"shutil rmtree in python examples\",\"shutil rmtree permission denied\",\"shutil.rmtree in python\"],\"articleSection\":[\"Tutorials\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.pythonpool.com\\\/python-shutil-rmtree\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.pythonpool.com\\\/python-shutil-rmtree\\\/\",\"url\":\"https:\\\/\\\/www.pythonpool.com\\\/python-shutil-rmtree\\\/\",\"name\":\"shutil.rmtree(): Delete a Directory Tree Safely\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.pythonpool.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.pythonpool.com\\\/python-shutil-rmtree\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.pythonpool.com\\\/python-shutil-rmtree\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.pythonpool.com\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/python-shutil-rmtree-directory-delete-guide-pythonpool.png\",\"datePublished\":\"2022-03-11T11:06:47+00:00\",\"dateModified\":\"2026-07-13T07:08:58+00:00\",\"description\":\"Use shutil.rmtree() to remove a Python directory tree safely, with path checks, read-only cleanup, error handling, and symlink cautions.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.pythonpool.com\\\/python-shutil-rmtree\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.pythonpool.com\\\/python-shutil-rmtree\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.pythonpool.com\\\/python-shutil-rmtree\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.pythonpool.com\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/python-shutil-rmtree-directory-delete-guide-pythonpool.png\",\"contentUrl\":\"https:\\\/\\\/www.pythonpool.com\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/python-shutil-rmtree-directory-delete-guide-pythonpool.png\",\"width\":1350,\"height\":650,\"caption\":\"Python shutil.rmtree directory delete guide\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.pythonpool.com\\\/python-shutil-rmtree\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.pythonpool.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"shutil.rmtree(): Delete a Directory Tree Safely\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.pythonpool.com\\\/#website\",\"url\":\"https:\\\/\\\/www.pythonpool.com\\\/\",\"name\":\"Python Pool\",\"description\":\"Practical Python tutorials, error fixes, code examples, and project guides.\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.pythonpool.com\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.pythonpool.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.pythonpool.com\\\/#organization\",\"name\":\"Python Pool\",\"url\":\"https:\\\/\\\/www.pythonpool.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.pythonpool.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.pythonpool.com\\\/wp-content\\\/uploads\\\/2020\\\/08\\\/aa.png\",\"contentUrl\":\"https:\\\/\\\/www.pythonpool.com\\\/wp-content\\\/uploads\\\/2020\\\/08\\\/aa.png\",\"width\":452,\"height\":185,\"caption\":\"Python Pool\"},\"image\":{\"@id\":\"https:\\\/\\\/www.pythonpool.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/x.com\\\/pythonpool\",\"https:\\\/\\\/www.youtube.com\\\/c\\\/pythonpool\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.pythonpool.com\\\/#\\\/schema\\\/person\\\/5e8aa48e7557450d345c829305550688\",\"name\":\"Vishnu Venkatesh\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/8d399a4488a19871b08a11ebd884e233b04c76d12edc4c7278a79d69df853d75?s=96&d=wavatar&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/8d399a4488a19871b08a11ebd884e233b04c76d12edc4c7278a79d69df853d75?s=96&d=wavatar&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/8d399a4488a19871b08a11ebd884e233b04c76d12edc4c7278a79d69df853d75?s=96&d=wavatar&r=g\",\"caption\":\"Vishnu Venkatesh\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"shutil.rmtree(): Delete a Directory Tree Safely","description":"Use shutil.rmtree() to remove a Python directory tree safely, with path checks, read-only cleanup, error handling, and symlink cautions.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.pythonpool.com\/python-shutil-rmtree\/","og_locale":"en_US","og_type":"article","og_title":"shutil.rmtree(): Delete a Directory Tree Safely","og_description":"Delete a directory tree with shutil.rmtree() only after validating the target, previewing its contents, and handling cleanup errors.","og_url":"https:\/\/www.pythonpool.com\/python-shutil-rmtree\/","og_site_name":"Python Pool","article_published_time":"2022-03-11T11:06:47+00:00","article_modified_time":"2026-07-13T07:08:58+00:00","og_image":[{"url":"https:\/\/www.pythonpool.com\/wp-content\/uploads\/2026\/07\/python-shutil-rmtree-directory-delete-guide-pythonpool.png","type":"","width":"","height":""}],"author":"Vishnu Venkatesh","twitter_card":"summary_large_image","twitter_title":"Python Pool","twitter_description":"Practical Python tutorials, error fixes, code examples, and project guides.","twitter_image":"https:\/\/www.pythonpool.com\/wp-content\/uploads\/2026\/07\/python-shutil-rmtree-directory-delete-guide-pythonpool.png","twitter_creator":"@pythonpool","twitter_site":"@pythonpool","twitter_misc":{"Written by":"Vishnu Venkatesh","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.pythonpool.com\/python-shutil-rmtree\/#article","isPartOf":{"@id":"https:\/\/www.pythonpool.com\/python-shutil-rmtree\/"},"author":{"name":"Vishnu Venkatesh","@id":"https:\/\/www.pythonpool.com\/#\/schema\/person\/5e8aa48e7557450d345c829305550688"},"headline":"shutil.rmtree(): Delete a Directory Tree Safely","datePublished":"2022-03-11T11:06:47+00:00","dateModified":"2026-07-13T07:08:58+00:00","mainEntityOfPage":{"@id":"https:\/\/www.pythonpool.com\/python-shutil-rmtree\/"},"wordCount":1064,"commentCount":0,"publisher":{"@id":"https:\/\/www.pythonpool.com\/#organization"},"image":{"@id":"https:\/\/www.pythonpool.com\/python-shutil-rmtree\/#primaryimage"},"thumbnailUrl":"https:\/\/www.pythonpool.com\/wp-content\/uploads\/2026\/07\/python-shutil-rmtree-directory-delete-guide-pythonpool.png","keywords":["access is denied error while using shutil.rmtree windows","access is denied shutil.rmtree","shutil rmtree folder not empty","shutil rmtree hidden files","shutil rmtree in python examples","shutil rmtree permission denied","shutil.rmtree in python"],"articleSection":["Tutorials"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.pythonpool.com\/python-shutil-rmtree\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.pythonpool.com\/python-shutil-rmtree\/","url":"https:\/\/www.pythonpool.com\/python-shutil-rmtree\/","name":"shutil.rmtree(): Delete a Directory Tree Safely","isPartOf":{"@id":"https:\/\/www.pythonpool.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.pythonpool.com\/python-shutil-rmtree\/#primaryimage"},"image":{"@id":"https:\/\/www.pythonpool.com\/python-shutil-rmtree\/#primaryimage"},"thumbnailUrl":"https:\/\/www.pythonpool.com\/wp-content\/uploads\/2026\/07\/python-shutil-rmtree-directory-delete-guide-pythonpool.png","datePublished":"2022-03-11T11:06:47+00:00","dateModified":"2026-07-13T07:08:58+00:00","description":"Use shutil.rmtree() to remove a Python directory tree safely, with path checks, read-only cleanup, error handling, and symlink cautions.","breadcrumb":{"@id":"https:\/\/www.pythonpool.com\/python-shutil-rmtree\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.pythonpool.com\/python-shutil-rmtree\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.pythonpool.com\/python-shutil-rmtree\/#primaryimage","url":"https:\/\/www.pythonpool.com\/wp-content\/uploads\/2026\/07\/python-shutil-rmtree-directory-delete-guide-pythonpool.png","contentUrl":"https:\/\/www.pythonpool.com\/wp-content\/uploads\/2026\/07\/python-shutil-rmtree-directory-delete-guide-pythonpool.png","width":1350,"height":650,"caption":"Python shutil.rmtree directory delete guide"},{"@type":"BreadcrumbList","@id":"https:\/\/www.pythonpool.com\/python-shutil-rmtree\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.pythonpool.com\/"},{"@type":"ListItem","position":2,"name":"shutil.rmtree(): Delete a Directory Tree Safely"}]},{"@type":"WebSite","@id":"https:\/\/www.pythonpool.com\/#website","url":"https:\/\/www.pythonpool.com\/","name":"Python Pool","description":"Practical Python tutorials, error fixes, code examples, and project guides.","publisher":{"@id":"https:\/\/www.pythonpool.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.pythonpool.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.pythonpool.com\/#organization","name":"Python Pool","url":"https:\/\/www.pythonpool.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.pythonpool.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.pythonpool.com\/wp-content\/uploads\/2020\/08\/aa.png","contentUrl":"https:\/\/www.pythonpool.com\/wp-content\/uploads\/2020\/08\/aa.png","width":452,"height":185,"caption":"Python Pool"},"image":{"@id":"https:\/\/www.pythonpool.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/pythonpool","https:\/\/www.youtube.com\/c\/pythonpool"]},{"@type":"Person","@id":"https:\/\/www.pythonpool.com\/#\/schema\/person\/5e8aa48e7557450d345c829305550688","name":"Vishnu Venkatesh","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/8d399a4488a19871b08a11ebd884e233b04c76d12edc4c7278a79d69df853d75?s=96&d=wavatar&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/8d399a4488a19871b08a11ebd884e233b04c76d12edc4c7278a79d69df853d75?s=96&d=wavatar&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/8d399a4488a19871b08a11ebd884e233b04c76d12edc4c7278a79d69df853d75?s=96&d=wavatar&r=g","caption":"Vishnu Venkatesh"}}]}},"_links":{"self":[{"href":"https:\/\/www.pythonpool.com\/wp-json\/wp\/v2\/posts\/20200","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.pythonpool.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.pythonpool.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.pythonpool.com\/wp-json\/wp\/v2\/users\/28"}],"replies":[{"embeddable":true,"href":"https:\/\/www.pythonpool.com\/wp-json\/wp\/v2\/comments?post=20200"}],"version-history":[{"count":42,"href":"https:\/\/www.pythonpool.com\/wp-json\/wp\/v2\/posts\/20200\/revisions"}],"predecessor-version":[{"id":41837,"href":"https:\/\/www.pythonpool.com\/wp-json\/wp\/v2\/posts\/20200\/revisions\/41837"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.pythonpool.com\/wp-json\/wp\/v2\/media\/33784"}],"wp:attachment":[{"href":"https:\/\/www.pythonpool.com\/wp-json\/wp\/v2\/media?parent=20200"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.pythonpool.com\/wp-json\/wp\/v2\/categories?post=20200"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.pythonpool.com\/wp-json\/wp\/v2\/tags?post=20200"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}