{"id":70093,"date":"2005-04-05T17:11:00","date_gmt":"2005-04-05T17:11:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2005\/04\/05\/how-can-i-delete-a-folder-and-all-its-subfolders\/"},"modified":"2005-04-05T17:11:00","modified_gmt":"2005-04-05T17:11:00","slug":"how-can-i-delete-a-folder-and-all-its-subfolders","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/how-can-i-delete-a-folder-and-all-its-subfolders\/","title":{"rendered":"How Can I Delete a Folder and All Its Subfolders?"},"content":{"rendered":"<p><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Question\" height=\"34\" alt=\"Hey, Scripting Guy! Question\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\"> \n<P>Hey Scripting Guy! How can I delete a folder and all its subfolders?<BR><BR>&#8212; FB<\/P><IMG height=\"5\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" border=\"0\"><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Answer\" height=\"34\" alt=\"Hey, Scripting Guy! Answer\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\"><A href=\"http:\/\/go.microsoft.com\/fwlink\/?linkid=68779&amp;clcid=0x409\"><IMG class=\"farGraphic\" title=\"Script Center\" height=\"288\" alt=\"Script Center\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/ad.jpg\" width=\"120\" align=\"right\" border=\"0\"><\/A> \n<P>Hey, FB. You know, a lot of people think the Scripting Guys know everything there is to know about scripting. Let\u2019s put it this way: we wish. In fact, it\u2019s only when we begin to think that we <I>do<\/I> know something about scripting that we get ourselves into trouble.<\/P>\n<P>Take (please!) this seemingly-simple little question about deleting a folder and all its subfolders. One of the Scripting Guys (Greg asked us not to mention his name, to save him from embarrassment) thought this was easy; in fact, he already <I>had<\/I> a script that could delete a folder and its subfolders:<\/P><PRE class=\"codeSample\">strComputer = &#8220;.&#8221;\nSet objWMIService = GetObject(&#8220;winmgmts: \\\\&#8221; &amp; strComputer &amp; &#8220;\\root\\cimv2&#8221;)<\/p>\n<p>Set colFolders = objWMIService.ExecQuery _\n    (&#8220;Select * from Win32_Directory where Name = &#8216;c:\\\\Scripts'&#8221;)<\/p>\n<p>For Each objFolder in colFolders\n    errResults = objFolder.Delete\nNext\n<\/PRE>\n<P>Our unnamed Scripting Guy grabbed the script, did a quick test on his Windows XP Service Pack 1 computer and on a Windows 2000 computer, and discovered that the script worked just fine. With yet another job well done, he then took the rest of the day off and began planning how he would spend the huge bonus he would undoubtedly receive for having successfully solved this problem.<\/P>\n<P>It was only later that another Scripting Guy (and &#8211; alas &#8211; the newest member of the team at that) pointed out that his script &#8211; which worked perfectly well back in the Dark Ages of computing &#8211; no longer functioned in the modern world; in particular, it failed on any Windows XP computer running Service Pack 2. Why? Well, in Service Pack 1 you delete a folder and all its contents, <I>including any subfolders<\/I>, with no questions asked. In Service Pack 2, however, the behavior of the Win32_Directory class has changed. On a computer running SP2, a folder cannot be deleted if it contains even a single subfolder; instead, you generate a \u201cFolder not empty\u201d error. Ouch! In fact, using WMI the only way to delete a folder in SP2 is to first delete all its subfolders. And, of course, before you can delete a subfolder you have to delete all of its subfolders. And before you can delete any of those &#8211; well, it just goes on and on from there.<\/P>\n<P>Of course a lesser person would have given up at that point, and just told you that, \u201cThere\u2019s no way to delete a folder and all its contents.\u201d And that\u2019s exactly what our anonymous Scripting Guy was going to do. However, under intense pressure from his colleagues, he came up with this solution instead, one that creates a list of the entire folder tree and then methodically deletes folders from the bottom to the top. And don\u2019t worry, we\u2019ll tell you what that all means in a minute.<\/P>\n<P>Here\u2019s a script that ought to work on any version of Windows (or at least any version of Windows with WMI installed):<\/P><PRE class=\"codeSample\">Dim arrFolders()\nintSize = 0<\/p>\n<p>strComputer = &#8220;.&#8221;\nSet objWMIService = GetObject(&#8220;winmgmts:\\\\&#8221; &amp; strComputer &amp; &#8220;\\root\\cimv2&#8221;)<\/p>\n<p>strFolderName = &#8220;c:\\scripts\\archive&#8221;<\/p>\n<p>Set colSubfolders = objWMIService.ExecQuery _\n    (&#8220;Associators of {Win32_Directory.Name='&#8221; &amp; strFolderName &amp; &#8220;&#8216;} &#8221; _\n        &amp; &#8220;Where AssocClass = Win32_Subdirectory &#8221; _\n            &amp; &#8220;ResultRole = PartComponent&#8221;)<\/p>\n<p>ReDim Preserve arrFolders(intSize)\narrFolders(intSize) = strFolderName\nintSize = intSize + 1<\/p>\n<p>For Each objFolder in colSubfolders\n    GetSubFolders strFolderName\nNext<\/p>\n<p>Sub GetSubFolders(strFolderName)\n    Set colSubfolders2 = objWMIService.ExecQuery _\n        (&#8220;Associators of {Win32_Directory.Name='&#8221; &amp; strFolderName &amp; &#8220;&#8216;} &#8221; _\n            &amp; &#8220;Where AssocClass = Win32_Subdirectory &#8221; _\n                &amp; &#8220;ResultRole = PartComponent&#8221;)<\/p>\n<p>    For Each objFolder2 in colSubfolders2\n        strFolderName = objFolder2.Name\n        ReDim Preserve arrFolders(intSize)\n        arrFolders(intSize) = strFolderName\n        intSize = intSize + 1\n        GetSubFolders strFolderName\n    Next\nEnd Sub<\/p>\n<p>For i = Ubound(arrFolders) to 0 Step -1\n    strFolder = arrFolders(i)\n    strFolder = Replace(strFolder, &#8220;\\&#8221;, &#8220;\\\\&#8221;)\n    Set colFolders = objWMIService.ExecQuery _\n        (&#8220;Select * from Win32_Directory where Name = &#8216;&#8221; &amp; strFolder &amp; &#8220;&#8216;&#8221;)<\/p>\n<p>    For Each objFolder in colFolders\n        errResults = objFolder.Delete\n    Next\nNext\n<\/PRE>\n<P>We won\u2019t even attempt to walk through this code line-by-line; instead we\u2019ll just give you a rough idea of what we\u2019re doing, and why, and point you to some additional resources if you need more information.<\/P>\n<P>To begin with, let\u2019s say C:\\Scripts\\Archive looks like this:<\/P><IMG height=\"90\" alt=\"Folder Tree\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/foldertree.jpg\" width=\"199\" border=\"0\"> \n<P>We can\u2019t delete the Archive folder right away; that\u2019s because of Subfolder A1 and Subfolder A2. And we can\u2019t delete Subfolder A1 right away; that\u2019s because of Subfolder B1. To get rid of the Archive folder we need to:<\/P>\n<TABLE class=\"\" cellSpacing=\"0\" cellPadding=\"0\" border=\"0\">\n<TBODY>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>Delete Subfolder A2.<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>Delete Subfolder B1, clearing out Subfolder A1.<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>Delete Subfolder A1. With both Subfolder A1 and Subfolder A2 gone, we\u2019ll then be free to delete the Archive folder.<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>Delete the Archive folder.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<P>The approach we\u2019ve taken makes use of a recursive function; this function can identify all the subfolders of a folder, as well as all the subfolders of those subfolders. We won\u2019t discuss this function in any detail today; for an explanation of how it works, check out this <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/feb05\/hey0218.mspx\"><B>Hey, Scripting Guy!<\/B><\/A> column.<\/P>\n<P>By necessity, our recursive function starts with the first folder &#8211; Archive &#8211; and then works its way down the tree. Unfortunately, that\u2019s a bit of a problem; after all, we need to start deleting folders from the <I>bottom<\/I> of the tree and work our way up. There are probably lots of ways to handle this problem, but what we did was elect not to try deleting folders right away; instead, all we do is stash the folder paths into an array named arrFolders. Each time we encounter a new folder or subfolder we add the folder path to the array. When the recursive function finishes, our array will look like this:<\/P><PRE class=\"codeSample\">C:\\Scripts\\Archive\nC:\\Scripts\\Archive\\Subfolder A1\nC:\\Scripts\\Archive\\Subfolder A1\\Subfolder B1\nC:\\Scripts\\Archive\\Subfolder A2\n<\/PRE>\n<TABLE class=\"dataTable\" id=\"ELE\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD class=\"\">\n<P class=\"lastInCell\"><B>Note<\/B>. We used a so-called \u201cdynamic\u201d array in this script; for more information about dynamic arrays &#8211; and about weird-looking commands like <B>Redim Preserve<\/B> &#8211; please see this portion of the <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/guide\/sas_vbs_hbsi.mspx\"><B>Microsoft Windows 2000 Scripting Guide<\/B><\/A>.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>Trust us: we\u2019re well aware that this was <I>way<\/I> easier in Windows 2000. But at least now we\u2019re ready to start deleting folders. If you look at the items in our array, they happen to be exactly opposite of what we need; for example, the Archive folder is the first item in our array, but it has to be the last item that we delete. If we could invert the array &#8211; making the first last and the last first, to steal a phrase &#8211; we\u2019d be in business. That\u2019s where this block of code comes in:<\/P><PRE class=\"codeSample\">For i = Ubound(arrFolders) to 0 Step -1\n    strFolder = arrFolders(i)\n    strFolder = Replace(strFolder, &#8220;\\&#8221;, &#8220;\\\\&#8221;)\n    Set colFolders = objWMIService.ExecQuery _\n        (&#8220;Select * from Win32_Directory where Name = &#8216;&#8221; &amp; strFolder &amp; &#8220;&#8216;&#8221;)<\/p>\n<p>    For Each objFolder in colFolders\n        errResults = objFolder.Delete\n    Next\nNext\n<\/PRE>\n<P>What we\u2019re doing here is reading our array from the bottom up. We\u2019re creating a loop that starts with the very last item in the array; that\u2019s what the <B>Ubound<\/B> (upper bound) function is for. We\u2019re then going to work our way down to the first item in the array: item 0. (As you might recall, the first element in an array is always item 0, <I>not<\/I> item 1.) The <B>Step -1<\/B> function just means that we step backwards rather than forward: instead of going 0-1-2-3, we\u2019re going 3-2-1-0. This is how we can start deleting at the bottom of the tree.<\/P>\n<P>Of course, before we can do that we need to adjust the folder paths; that\u2019s what we do here:<\/P><PRE class=\"codeSample\">strFolder = Replace(strFolder, &#8220;\\&#8221;, &#8220;\\\\&#8221;)\n<\/PRE>\n<P>Our folder paths are going to look like this: C:\\Scripts\\Archive\\Subfolder A1\\Subfolder B1. That\u2019s fine, except that we need to include these paths in a WQL query. Consequently, we need to double up all the \\\u2019s, resulting in paths that look like this: C:\\\\Scripts\\\\Archive\\\\Subfolder A1\\\\Subfolder B1. We use the <B>Replace<\/B> function to replace each \\ with \\\\.<\/P>\n<P>You\u2019re right: there\u2019s <I>nothing<\/I> straightforward about this script, is there?<\/P>\n<P>With our new \\\\ folder paths we can then use WMI to connect to the folder in question and &#8211; at long last &#8211; use the <B>Delete<\/B> method to actually delete the folder. That\u2019s what happens here:<\/P><PRE class=\"codeSample\">Set colFolders = objWMIService.ExecQuery _\n    (&#8220;Select * from Win32_Directory where Name = &#8216;&#8221; &amp; strFolder &amp; &#8220;&#8216;&#8221;)<\/p>\n<p>For Each objFolder in colFolders\n    errResults = objFolder.Delete\nNext\n<\/PRE>\n<P>Having disposed of Subfolder B1, we can then start working our way up the tree, eventually deleting C:\\Scripts\\Archive.<\/P>\n<P>Five million lines of code later, we\u2019re done, and C:\\Scripts\\Archive has been deleted. We\u2019re not saying it\u2019s a particularly elegant solution, but it <I>is<\/I> a solution, and it will work on all versions of Windows. And because it uses WMI, it works equally well on remote machines as it does on the local computer.<\/P>\n<P>So there you have it: deleting a folder and all its subfolders, a subject we\u2019ve vowed never to deal with again. Well, at least not until the next service pack comes out \u2026.<\/P><BR>\n<DIV>\n<TABLE class=\"\" cellSpacing=\"0\" cellPadding=\"0\" width=\"100%\" border=\"0\">\n<TBODY>\n<TR>\n<TD class=\"\"><A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/apr05\/hey0405.mspx#top\"><IMG height=\"9\" alt=\"Top of page\" src=\"http:\/\/www.microsoft.com\/technet\/mnplibrary\/templates\/MNP2.Common\/images\/arrow_px_up.gif\" width=\"7\" border=\"0\"><\/A><A class=\"topOfPage\" href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/apr05\/hey0405.mspx#top\">Top of page<\/A><\/TD><\/TR><\/TBODY><\/TABLE><\/DIV><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey Scripting Guy! How can I delete a folder and all its subfolders?&#8212; FB Hey, FB. You know, a lot of people think the Scripting Guys know everything there is to know about scripting. Let\u2019s put it this way: we wish. In fact, it\u2019s only when we begin to think that we do know something [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[11,3,12,5,6],"class_list":["post-70093","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-folders","tag-scripting-guy","tag-storage","tag-vbscript","tag-wmi"],"acf":[],"blog_post_summary":"<p>Hey Scripting Guy! How can I delete a folder and all its subfolders?&#8212; FB Hey, FB. You know, a lot of people think the Scripting Guys know everything there is to know about scripting. Let\u2019s put it this way: we wish. In fact, it\u2019s only when we begin to think that we do know something [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/70093","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=70093"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/70093\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=70093"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=70093"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=70093"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}