{"id":64213,"date":"2007-08-17T01:37:00","date_gmt":"2007-08-17T01:37:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2007\/08\/17\/how-can-i-copy-the-folder-structure-of-a-folder\/"},"modified":"2007-08-17T01:37:00","modified_gmt":"2007-08-17T01:37:00","slug":"how-can-i-copy-the-folder-structure-of-a-folder","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/how-can-i-copy-the-folder-structure-of-a-folder\/","title":{"rendered":"How Can I Copy the Folder Structure of a Folder?"},"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 copy the folder structure of a folder (that is, a folder and all its subfolders) without copying the files as well?<BR><BR>&#8212; AS <\/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, AS. If you\u2019re one of the many people who simply can\u2019t get through the day without knowing what the Scripting Guy who writes this column is up to as he traipses through Italy, well, here\u2019s the latest update: today the Scripting Family hops on a plane and heads for Venice. And what if you\u2019re one of the many people who can (and would actually <I>prefer<\/I> to) get through the day without knowing what the Scripting Guy who writes this column is up to as he traipses through Italy? Well, we have good news for you, too: the Scripting Money is beginning to run out, so it\u2019s just a matter of time before the Scripting Guy who writes this column comes home and stops bothering you with details about his trip to Europe.<\/P>\n<P>At which point he resumes bothering you with details about the Scripting Son\u2019s baseball games.<\/P>\n<P>But what if you\u2019re one of those people who just wants to know how to copy the folder structure of a folder without copying all the files as well? Well, guess what? There\u2019s good news for you, too: we just happen to have a script that does that very thing.<\/P>\n<P><I>Hey, Scripting Guy!<\/I>, the daily column with a little something for everyone! <\/P>\n<P>Including the following script:<\/P><PRE class=\"codeSample\">On Error Resume Next<\/p>\n<p>Dim arrFolders()\nintSize = 0<\/p>\n<p>strComputer = &#8220;.&#8221;<\/p>\n<p>Set objWMIService = GetObject(&#8220;winmgmts:\\\\&#8221; &amp; strComputer &amp; &#8220;\\root\\cimv2&#8221;)<\/p>\n<p>strFolderName = &#8220;c:\\scripts&#8221;<\/p>\n<p>GetSubFolders strFolderName<\/p>\n<p>Sub GetSubFolders(strFolderName)\n    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>    For Each objFolder in colSubfolders\n        strFolderName = objFolder.Name\n        ReDim Preserve arrFolders(intSize)\n        arrFolders(intSize) = strFolderName\n        intSize = intSize + 1\n        GetSubFolders strFolderName\n    Next\nEnd Sub<\/p>\n<p>Set objFSO = CreateObject(&#8220;Scripting.FileSystemObject&#8221;)<\/p>\n<p>For Each strFolder in arrFolders\n    strFolderName = strFolder \n    strNewFolder = Replace(strFolderName, &#8220;c:\\scripts&#8221;, &#8220;c:\\test&#8221;)\n    Set objFolder = objFSO.CreateFolder(strNewFolder)\nNext\n<\/PRE>\n<P>Yes, we know: this <I>is<\/I> a scary-looking script, isn\u2019t it? That\u2019s because there\u2019s no simple, straightforward method for getting at nested subfolders; that is, folders inside of folders inside of folders. (Or at least not in VBScript; in <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/topics\/msh\/cmdlets\/get-childitem.mspx\"><B>Windows PowerShell<\/B><\/A> there <I>is<\/I> a simple, straightforward method for getting at nested subfolders.) Therefore, we need to use a recursive subroutine: a subroutine that can call itself, and as many times as it needs to. Recursive subroutines aren\u2019t exactly intuitive, which explains why the code looks as scary as it does.<\/P>\n<P>Our advice? If you\u2019d like to know more about recursion, check out <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/guide\/sas_vbs_kove.mspx\"><B>this section<\/B><\/A> of the <I>Microsoft Windows 2000 Scripting Guide<\/I>. Otherwise, don\u2019t worry too much about it: just use today\u2019s script as-is, changing the names of the folders as needed.<\/P>\n<P>What we\u2019re going to do today is grab the name (or, more properly, the path) of every subfolder in C:\\Scripts and stash that information in an array; after that, we\u2019ll loop through the values in the array in order to copy that folder structure to C:\\Test. With that in mind, the first thing we do is initialize a dynamic array named arrFolders, then assign the value 0 to a counter variable named intSize. That\u2019s what\u2019s going on here:<\/P><PRE class=\"codeSample\">Dim arrFolders()\nintSize = 0\n<\/PRE>\n<P>After we connect to the WMI service on the local computer we assign the path of the parent folder (C:\\Scripts) to a variable named strFolderName. What we\u2019re going to do (in a minute) is execute a chunk of code that returns a collection of all the topmost subfolders for our parent folder. What do we mean by \u201ctopmost\u201d subfolders? Well, suppose we have a folder structure that looks like this:<\/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>C:\\Scripts<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>C:\\Scripts\\Folder 1<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>C:\\Scripts\\Folder 1\\Folder A<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>C:\\Scripts\\Folder 2<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>C:\\Scripts\\Folder 2\\Folder B<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<P>If C:\\Scripts is our parent folder (and it is), then the topmost subfolders are Folder 1 and Folder 2; these are the subfolders that are one level \u201cdown\u201d from the parent folder. What about Folder A and Folder B, folders nested <I>two<\/I> levels from the parent? Well, that\u2019s the problem: deeply-nested subfolders like this are difficult to get at. In turn, that\u2019s why we need the recursive subroutine.<\/P>\n<P>Got all that? Good. Now let\u2019s have some fun:<\/P><PRE class=\"codeSample\">GetSubFolders strFolderName\n<\/PRE>\n<P>OK, so maybe \u201cfun\u201d wasn\u2019t the right word; how about \u201cNow let\u2019s get to work retrieving all the folder and subfolder names\u201d? What we\u2019re doing here is calling our recursive subroutine (a subroutine named GetSubFolders), passing the path to the parent folder as the sole subroutine parameter. In case you\u2019ve forgotten, the GetSubFolders subroutine looks like this:<\/P><PRE class=\"codeSample\">Sub GetSubFolders(strFolderName)\n    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>    For Each objFolder in colSubfolders\n        strFolderName = objFolder.Name\n        ReDim Preserve arrFolders(intSize)\n        arrFolders(intSize) = strFolderName\n        intSize = intSize + 1\n        GetSubFolders strFolderName\n    Next\nEnd Sub\n<\/PRE>\n<P>Yes, this <I>is<\/I> where things start to get a little weird. Inside the subroutine the first thing we do is execute an <B>Associators Of<\/B> query that returns a collection of all the topmost subfolders of C:\\Scripts. How do we <I>know<\/I> this query returns the subfolders of the folder C:\\Scripts? Well, for one thing, we\u2019re getting back instances of the <B>Win32_Subdirectory<\/B> class; instances of that class just happen to be subfolders. For another, we know that the parent folder <I>must<\/I> be C:\\Scripts because that\u2019s the value of the variable strFolderName.<\/P>\n<P><I>That\u2019s<\/I> how we know that this query returns the subfolders of the folder C:\\Scripts.<\/P>\n<P>As we noted, the Associators Of query returns a collection of all the topmost subfolders in the folder C:\\Scripts (for example, C:\\Scripts\\Folder 1 and C:\\Scripts\\Folder 2). Our next step is to set up a For Each loop that walks through this collection of subfolders. Inside that loop, we use this line of code to grab the folder <B>Name<\/B> (that is, the folder path) and assign <I>that<\/I> value to the variable strFolderName:<\/P><PRE class=\"codeSample\">strFolderName = objFolder.Name\n<\/PRE>\n<P>After that, we use the following block of code to resize the array arrFolders, taking care to maintain any existing data in that array. We assign the path to the first subfolder (e.g., C:\\Scripts\\Folder 1) to the first item (item 0) in the array, then increment the value of our counter variable intSize by 1:<\/P><PRE class=\"codeSample\">ReDim Preserve arrFolders(intSize)\narrFolders(intSize) = strFolderName\nintSize = intSize + 1\n<\/PRE>\n<P>Why do we increment the value of the counter variable? That\u2019s easy. So far we\u2019ve added one folder to the array, making that single item array item 0. When the time comes to add another folder to the array, that subfolder needs to be added as item 1 in the array; that means that the value of our counter variable intSize <I>also<\/I> needs to be equal to 1.<\/P>\n<P>That brings us to this line of code:<\/P><PRE class=\"codeSample\">GetSubFolders strFolderName\n<\/PRE>\n<P>Yes, you <I>have<\/I> seen that line of code before: once again we\u2019re calling the subroutine GetSubFolders, this time passing the value C:\\Scripts\\Folder 1 as the subroutine parameter. And yes, we\u2019re doing that even though we\u2019re already inside the subroutine GetSubFolders; such is the nature of a recursive function. What this is going to do is run the subroutine against the folder C:\\Scripts\\Folder 1, pulling out the topmost subfolders of <I>that<\/I> folder. And then the subroutine will run against <I>those<\/I> folders, looking for <I>their<\/I> subfolders. This recursive process will continue until we run out of folders in the folder tree, by which time the paths to all of these folders will have been added to the array arrFolders.<\/P>\n<P>We know: we get a headache just thinking about that, too. Fortunately, however, we don\u2019t have to think about it too much; instead, VBScript does all the hard work (like keeping track of where it is in the folder structure and what it needs to do next) for us.<\/P>\n<P>So what happens when we <I>do<\/I> finish adding all the folder paths to the array arrFolders? Well, for starters, we create an instance of the <B>Scripting.FileSystemObject<\/B> object, the object used to create new folders. We then set up a For Each loop to walk us through each of the folder paths in arrFolders, folder paths similar to this:<\/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>C:\\Scripts\\Folder 1<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>C:\\Scripts\\Folder 1\\Folder A<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>C:\\Scripts\\Folder 2<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>C:\\Scripts\\Folder 2\\Folder B<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<P>Needless to say, those are the paths to the existing folders; what we need to do now is copy all those folders to C:\\Test. Admittedly, there are several different ways we can do this; we decided the easiest approach was to start out by using the <B>Replace<\/B> function to replace each instance of C:\\Scripts with C:\\Test. For the first item in the array that\u2019s going to give us the following folder path:<\/P><PRE class=\"codeSample\">C:\\Test\\Folder 1\n<\/PRE>\n<P>And guess what? That just happens to be one of the paths we need in order to copy the folder structure of C:\\Scripts to C:\\Test. That means that all we have to do now is call the <B>CreateFolder<\/B> method (passing along this new folder name as the method parameter). Just like that, we\u2019ve copied part of the folder structure to C:\\Test, but without copying any files. And then we simply loop around and repeat the process with the next folder in the array.<\/P>\n<P>When all is said and done C:\\Test will contain the following subfolders:<\/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>C:\\Test\\Folder 1<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>C:\\Test\\Folder 1\\Folder A<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>C:\\Test\\Folder 2<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>C:\\Test\\Folder 2\\Folder B<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<P>Which are the very subfolders C:\\Test <I>should<\/I> contain.<\/P>\n<P>As we noted earlier, today the Scripting Family heads to Venice. No doubt all of you are familiar with Venice, the city built smack-dab in the middle of the Venetian Lagoon. (Most of the buildings actually rest on wood pilings driven into the sea floor.) For much of the 20<SUP>th<\/SUP> century Venice was slowly sinking into the lagoon; this was due to artesian wells that were sunk along the outskirts of the town. A ban on artesian wells enacted in the 1960s has slowed the sinking process; however, experts remain divided on whether this has <I>stopped<\/I> the sinking process. <\/P>\n<P>All of this, of course, is one reason why the Scripting Guy who writes this column has such an affinity for the city of Venice. Something that is slowly sinking away into nothingness? If that isn\u2019t a perfect description of his career path at Microsoft, well, we don\u2019t know what is.<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! How can I copy the folder structure of a folder (that is, a folder and all its subfolders) without copying the files as well?&#8212; AS Hey, AS. If you\u2019re one of the many people who simply can\u2019t get through the day without knowing what the Scripting Guy who writes this column is [&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],"class_list":["post-64213","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-folders","tag-scripting-guy","tag-storage","tag-vbscript"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! How can I copy the folder structure of a folder (that is, a folder and all its subfolders) without copying the files as well?&#8212; AS Hey, AS. If you\u2019re one of the many people who simply can\u2019t get through the day without knowing what the Scripting Guy who writes this column is [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/64213","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=64213"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/64213\/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=64213"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=64213"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=64213"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}