{"id":64693,"date":"2007-06-08T23:34:00","date_gmt":"2007-06-08T23:34:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2007\/06\/08\/how-can-i-get-a-list-of-all-the-pdf-files-in-a-folder-and-its-subfolders\/"},"modified":"2007-06-08T23:34:00","modified_gmt":"2007-06-08T23:34:00","slug":"how-can-i-get-a-list-of-all-the-pdf-files-in-a-folder-and-its-subfolders","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/how-can-i-get-a-list-of-all-the-pdf-files-in-a-folder-and-its-subfolders\/","title":{"rendered":"How Can I Get a List of All the PDF Files in a Folder and 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 get a list of all the .PDF files (only the file names; I don\u2019t want the file path or file extension) in a folder and its subfolders, and then put that list into a text file?<BR><BR>&#8212; PS <\/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, PS. You know, PS, this is actually a hard question; far harder and far more complicated than it might sound. On top of that, the Scripting Guy who writes this column is on vacation; he doesn\u2019t really have time to be bothered with stuff like this.<\/P>\n<P>Well, OK, technically he\u2019s not really on vacation; technically he\u2019s attending \u2013 and working at \u2013 <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/topics\/teched07\/default.mspx\"><B>TechEd 2007<\/B><\/A>. But, come on PS. The Scripting Guy who writes this column is in Orlando; you know, Disney World, Universal Studios, Sea World. The truth is, there\u2019s no way he\u2019s going to spend his time in Orlando writing scripts that can retrieve a list of all the PDF files in a folder and its subfolders. Sorry, but it\u2019s just not going to happen.<\/P>\n<P>Or at least we didn\u2019t think it would happen. By an astonishing coincidence, however, Epcot Center just opened a brand-new attraction: Dr. Scripto\u2019s Wild Ride. And guess what happens when you ride this new ride? That\u2019s right: you get a queasy feeling in your stomach. However, you also get a script that can retrieve a list of all the PDF files in a folder and its subfolders (it\u2019s kind of a weird ride):<\/P><PRE class=\"codeSample\">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:\\Test&#8221;<\/p>\n<p>Set objFSO = CreateObject(&#8220;Scripting.FileSystemObject&#8221;)\nSet objTextFile = objFSO.CreateTextFile(&#8220;C:\\Scripts\\Test.txt&#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>Set colFiles = objWMIService.ExecQuery _\n    (&#8220;ASSOCIATORS OF {Win32_Directory.Name='&#8221; &amp; strFolderName &amp; &#8220;&#8216;} Where &#8221; _\n        &amp; &#8220;ResultClass = CIM_DataFile&#8221;)<\/p>\n<p>For Each objFile in colFiles\n    If objFile.Extension = &#8220;pdf&#8221; Then\n        objTextFile.WriteLine objFile.FileName \n    End If\nNext<\/p>\n<p>For Each objFolder in colSubfolders\n    GetSubFolders strFolderName\nNext<\/p>\n<p>Sub GetSubFolders(strFolderName)<\/p>\n<p>    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<\/p>\n<p>    Set colFiles = objWMIService.ExecQuery _\n        (&#8220;ASSOCIATORS OF {Win32_Directory.Name='&#8221; &amp; strFolderName &amp; &#8220;&#8216;} Where &#8221; _\n            &amp; &#8220;ResultClass = CIM_DataFile&#8221;)<\/p>\n<p>    For Each objFile in colFiles\n        If objFile.Extension = &#8220;pdf&#8221; Then\n            objTextFile.WriteLine objFile.FileName \n        End If\n    Next<\/p>\n<p>        GetSubFolders strFolderName\n    Next\nEnd Sub\n<\/PRE>\n<P>We tried to warn you: this is a complicated procedure, far more complicated than it probably should be. That\u2019s because neither WMI nor the FileSystemObject provide a simple, straightforward way to work with folders and subfolders. (This, by the way, is one area where Windows PowerShell represents a big improvement over previous technologies.) Because of that, we need to use a recursive function in order to get at the files in a folder, the files in that folder\u2019s subfolders, and the files in the sub-subfolders of those subfolders. We don\u2019t have time to explain recursion in any detail today. (Did we mention that we\u2019re on vacation?) However, you can get an overview of recursion and recursive functions by taking a peek at the <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/guide\/sas_vbs_kove.mspx\"><B>Microsoft Windows 2000 Scripting Guide<\/B><\/A>.<\/P>\n<P>All right, let\u2019s get down to business and try to get through this before the amusement parks close for the day. We start out by connecting to the WMI service on the local computer. (Although by assigning a computer name to the variable strComputer we could just as easily run this script against a remote machine.) We then assign the parent folder name to the variable strFolderName. Because we want to look at the folder C:\\Test (as well as all its subfolders) we assign strFolderName the value C:\\Test:<\/P><PRE class=\"codeSample\">strFolderName = &#8220;C:\\Test&#8221;\n<\/PRE>\n<P>Makes sense, right? And because this is as good a time as any, we next create an instance of the Scripting.FileSystemObject and use the <B>CreateTextFile<\/B> method to create a text file named C:\\Scripts\\Test.txt:<\/P><PRE class=\"codeSample\">Set objFSO = CreateObject(&#8220;Scripting.FileSystemObject&#8221;)\nSet objTextFile = objFSO.CreateTextFile(&#8220;C:\\Scripts\\Test.txt&#8221;)\n<\/PRE>\n<P>That brings us to this line of code:<\/P><PRE class=\"codeSample\">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;)\n<\/PRE>\n<P>What we\u2019re doing here is using an Associators Of query to get a list of all the subfolders of the folder C:\\Test. It might not look like it, but what our query is really saying this: Get me a list of all the items associated with the directory C:\\Test, provided that those items are subdirectories (Where AssocClass = Win32_Subdirectory). <\/P>\n<P>When all is said and done this query brings back a list of all the top-level subfolders in C:\\Test; for example, C:\\Test\\Folder1 and C:\\Test\\Folder2. What it doesn\u2019t bring back are any second-level folders; for example, we won\u2019t get back a folder like C:\\Test\\Folder1\\SubfolderA. To get at these sub-subfolders (that is, subfolders of a subfolder) we need to use a recursive query. That\u2019s what the subroutine GetSubFolders is for. Programmatically, we pass this subroutine the name of each subfolder we find (for example, C:\\Test\\Folder1 and C:Test\\Folder2); in turn, the subroutine queries each of these subfolders for PDF files and for any sub-subfolders. If there are some sub-subfolders, the subroutine will automatically call itself and look for any sub-sub-subfolders.<\/P>\n<P>Confused? To be honest, so are we. But don\u2019t worry about it; just leave the code as-is and give it a try. To search a different folder (that is, a folder other than C:\\Test) simply change the value of the variable strFolderName to the name of the folder you want to work with. For example, if you want to search C:\\Windows then use this line of code:<\/P><PRE class=\"codeSample\">strFolderName = &#8220;C:\\Windows&#8221;\n<\/PRE>\n<P>Whoa, wait a second; we aren\u2019t done yet. Before we start calling subroutines we need to list any PDF files that happen to live in our parent folder, C:\\Test. To do that, we use this line of code to return a collection of all the files (instances of the CIM_DataFile class) found in C:\\Test (which is, as you recall, the value we assigned to the variable strFolderName):<\/P><PRE class=\"codeSample\">Set colFiles = objWMIService.ExecQuery _\n    (&#8220;ASSOCIATORS OF {Win32_Directory.Name='&#8221; &amp; strFolderName &amp; &#8220;&#8216;} Where &#8221; _\n        &amp; &#8220;ResultClass = CIM_DataFile&#8221;)\n<\/PRE>\n<P>Next we use this block of code to check each file and see if it has the file extension PDF (note that, in WMI, the dot is not part of the file extension):<\/P><PRE class=\"codeSample\">For Each objFile in colFiles\n    If objFile.Extension = &#8220;pdf&#8221; Then\n        objTextFile.WriteLine objFile.FileName \n    End If\nNext\n<\/PRE>\n<P>If we do have a PDF file then we use the WriteLine method to write the FileName to our text file:<\/P><PRE class=\"codeSample\">objTextFile.WriteLine objFile.FileName\n<\/PRE>\n<P>Needless to say, the FileName property is just the name of the file, without the path or the file extension. For example, if our first file is C:\\Test\\MyFile.pdf we\u2019ll end up writing the following to the text file:<\/P><PRE class=\"codeSample\">MyFile\n<\/PRE>\n<P>That takes care of all the files in the parent folder, C:\\Test. Now, what about files in any subfolders of C:\\Test? That\u2019s what this block of code is for:<\/P><PRE class=\"codeSample\">For Each objFolder in colSubfolders\n    GetSubFolders strFolderName\nNext\n<\/PRE>\n<P>What we\u2019re doing here is looping through the collection of subfolders; for each subfolder in C:\\Test we\u2019re calling the recursive function GetSubFolders, passing the folder path as the sole parameter:<\/P><PRE class=\"codeSample\">GetSubFolders strFolderName\n<\/PRE>\n<P>This is difficult to visualize, but GetSubfolders is going to do the exact same thing we just finished doing. Let\u2019s say that our first subfolder is C:\\Test\\Folder1. The subroutine is going to start out by looking for all the PDF files in C:\\Test\\Folder1; if it finds any it\u2019s going to write the names of those files to the text file. <\/P>\n<P>After that, GetSubFolders is going to run a query and see if C:\\Test\\Folder1 has any subfolders of its own. Suppose it does; what happens then? Well, in that case the subroutine is going to call itself, this time passing the name of each sub-subfolder as the subroutine parameter. Like we said, this can give you a headache just thinking about it. But suppose we have a sub-subfolder named C:\\Test\\Folder1\\SubfolderA. The subroutine will call itself and then look for PDF files in this sub-subfolder; after that, it will check to see in SubfolderA has any sub-sub-subfolders, and then, if necessary, the subroutine will call itself yet again. This will continue until its reached the end of the line and run out of folders.<\/P>\n<P>Crazy, huh? Fortunately, VBScript does all the hard work here. All you need to do is call the recursive function (which, now that we think about it, is really a recursive subroutine, isn\u2019t it?). VBScript will take care of the rest, keeping track of which folders you\u2019ve looked at and which folders you haven\u2019t looked at. Amazingly enough, by the time it finishes, this script will have looked at every single folder and subfolder in C:\\Test (even if these subfolders go several levels deep) and will have written the names of any and all PDF files to the text file C:\\Scripts\\Test.txt. If you don\u2019t believe us (and we don\u2019t blame you for being skeptical) give it a try and see for yourself.<\/P>\n<P>Before you start making vacation plans we should add that we were just kidding: Epcot Center does not have a new attraction called Dr. Scripto\u2019s Wild Ride. Based on today\u2019s column, that\u2019s probably just as well: we doubt that even Disney could afford the liability insurance for a ride this wild. <\/P>\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>. By the time most people read this, TechEd 2007 will be over and the Scripting Guys will be headed for the airport. But just because Teched is over that doesn\u2019t mean the fun is over; be sure and check out our <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/topics\/teched07\/default.mspx\"><B>TechEd 2007 page<\/B><\/A> for new articles, TechEd updates, and your chance to win a <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/funzone\/bobbles.mspx\"><B>Dr. Scripto bobblehead doll<\/B><\/A>. With TechEd 2007 the fun never ends!<\/P><\/TD><\/TR><\/TBODY><\/TABLE><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! How can I get a list of all the .PDF files (only the file names; I don\u2019t want the file path or file extension) in a folder and its subfolders, and then put that list into a text file?&#8212; PS Hey, PS. You know, PS, this is actually a hard question; far [&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":[38,11,3,4,12,14,5],"class_list":["post-64693","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-files","tag-folders","tag-scripting-guy","tag-scripting-techniques","tag-storage","tag-text-files","tag-vbscript"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! How can I get a list of all the .PDF files (only the file names; I don\u2019t want the file path or file extension) in a folder and its subfolders, and then put that list into a text file?&#8212; PS Hey, PS. You know, PS, this is actually a hard question; far [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/64693","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=64693"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/64693\/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=64693"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=64693"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=64693"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}