Extreme file and folder scripting: Listing a directory tree recursively. Day 1 – Using FilesSystemObject
BabyScript
If you attended Day 3 of the Scripting Week webcasts, "Scripting Files and Folders Makes Me Happy" https://go.microsoft.com/fwlink/?LinkId=30795, you may recall an odd and vaguely menacing script in the second section on WMI. It bristled with strange code and was labeled "Bonus: listing a folder tree," but we didn't discuss it. As Dr. Scripto said, merely looking at it could turn you to stone.
OK, so Dr. Scripto exaggerates a little. But we're going to call that script the Medusa Code because it sounds cool, kind of like the name of an action movie. We'll come back to the Medusa Code later, so stay on the edge of your seats. But for starters we're going to talk about what the Medusa Code was trying to accomplish in the first place: listing a directory tree recursively.
Ah, "recursively": there's a word that rolls off the tongue! Dr. Scripto loves to say it, although I had always suspected he wasn't too sure what it meant. I wasn't either, so I got out my dictionary and checked. There was no listing for "recursively," but it had a definition for "recursive": "1: of, relating to, or involving mathematical recursion."
Doh! Of course! Elementary, my dear Scripto.
Not being of a mathematical bent (I mean, being kind of bent, but not mathematically so), I forged ahead to the second definition: "2: of, relating to, or constituting a procedure that can repeat itself indefinitely or until a specified condition is met."
Hmmm, repeating itself indefinitely – sounds like Greg on a bad day. At that point, I threw the dictionary on my main pile (my office is organized by piles) and opened Notepad. When something doesn't make sense, it usually helps to open Notepad and start writing code.
At that point, Dr. Scripto whispered in my ear: "Don't worry about 'recursive.' Just write a script that walks a directory tree and lists all the files and folders in each branch." Aha, my muse had spoken. "But that's not repeating itself indefinitely," I whined. "No," replied Dr. Scripto, "just repeating itself until a specified condition is met. And that condition? That no more sub-folders can be found to recurse through."
If you'll recall from the webcast, with WMI you can easily display the names of all the files or folders on a computer or on a particular disk drive. But you probably don’t need to do that too often, and when you do, it can take a long time. When you get down to listing all the files or folders in a specific directory, you run into a shortcoming of some methods of the WMI file and folder classes: they only list the first level of files or folders even if there are sub-folders and files in them. In other words, they don't walk down all the branches of the directory tree. Ipso est, they're not recursive.
To show how to list a directory tree recursively, we're going to take a little detour back to the FileSystemObject. You'll recall that the webcast began with FSO and worked up to the WMI file and folder classes. So we'll follow the same path: before we get to WMI and the Medusa Code, it's a little bit easier to see how recursion works with FSO because the rest of the code is simpler.
Here’s a script that uses FSO to list all files in a folder and its sub-folders recursively (we'll call it Files-list-recurse-fso.vbs):
Const FOR_READING = 1
strFolder = "c:\ff"
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFSO.GetFolder(strFolder)
WScript.Echo objFolder.Path
Set colFiles = objFolder.Files
For Each objFile In colFiles
WScript.Echo objFile.Path
Next
ShowSubFolders(objFolder)
Sub ShowSubFolders(objFolder)
Set colFolders = objFolder.SubFolders
For Each objSubFolder In colFolders
WScript.Echo objSubFolder.Path
Set colFiles = objSubFolder.Files
For Each objFile In colFiles
WScript.Echo objFile.Path
Next
ShowSubFolders(objSubFolder)
Next
End Sub
Here's the output I got by running the script on a test folder:
C:\scripts>files-list-recurse-fso.vbs
C:\ff
C:\ff\disklog.txt
C:\ff\otherfile.txt
C:\ff\scriptlog.txt
C:\ff\servicelog.txt
C:\ff\servicestatus.txt
C:\ff\testfile.txt
C:\ff\ff1
C:\ff\ff1\disklog.txt
C:\ff\ff1\scriptlog.txt
C:\ff\ff1\ff3
C:\ff\ff1\ff3\disklog.txt
C:\ff\ff1\ff3\scriptlog.txt
C:\ff\ff2
C:\ff\ff2\disk.log
C:\ff\ff2\otherfile.txt
C:\ff\ff2\service.log
C:\ff\ff2\ff4
C:\ff\ff2\ff4\disk.log
C:\ff\ff2\ff4\otherfile.txt
C:\ff\ff2\ff4\service.log
The script is pretty straightforward for the most part. It gets the folder specified by the variable strFolder (in this case, c:\ff), then gets a collection of the files in that folder and loops through it with a For Each loop, displaying the full path of each one. A nice feature of the FileSystemObject is that Folder objects include a Files property that's a collection of all the files in the folder. How logical! How'd they ever come up with that?
But take a closer look at that Sub. What's it doing there? By jingo, Dr. Scripto, it's calling itself! Is that legal? Actually, as Dr. Scripto reassures me, that's what a recursive subroutine does, kind of like a dog chasing its own tail.
Besides the Files collection, FSO Folder objects have a SubFolders collection that includes — you'll never guess — all the folders contained within the folder. Very handy. We can use SubFolders to loop through each subfolder in the top-level folder, then get the collection the files in each and loop through that, displaying each one. Then, within the top For Each loop for subfolders, the sub-routine calls itself, passing itself the name of each subfolder in the collection successively. This is the key to how it can drill down through the levels of a directory tree. There are only three levels in the output example, but the script will keep drilling down — recursing — until it hits oil or the bottom level of the tree.
Is that crystal clear now? If you want to see this in action (and think you can handle this much fun), you could run the script in the Microsoft Script Debugger and watch the variables change through all those loops. If you start to get dizzy, just look away. For more information, Greg talked about how to run scripts in the debugger during our August 4 webcast "What Do You Want To Script Today?" https://msevents.microsoft.com/CUI/EventDetail.aspx?culture=en-US\&EventID=1032255873\&EventCategory=5
Incidentally, if you want to read a directory tree on a remote machine, FSO allows you to use a UNC path, such as "\\computer\share". So you could change line 2 to:
strFolder = "\\server1\c$\ff"
and display that tree recursively, provided of course that administrative shares are enabled on server1 and that you have administrative credentials on the machine.
More soon about doing this with WMI.
Comments
Anonymous
August 10, 2004
You're alive, dude!
Missed ya!Anonymous
December 19, 2006
Apparently I've sparked a discussion amongst the super-geniuses of LtU on various innovative languageAnonymous
October 10, 2007
A while back the Scripting Guys blogged about using recursion to list all the files in a directory and