How Do I Scan Through a Directory Tree
We can look at any directory on a hard drive and find some things in
common like - directory path/name and any files and sub folders it may contains.
Our goal is to write a generic and reusable function that will allow up to
handle any directory with any number of files and sub folders. A technique
called recursion, a function that calls itself, helps us out.
All we need to do is create a function that will examine a folder for its
contents (files and sub folders). Then, for every sub folder, repeat the
procedure (recursion).
Hopefully it will all be clear to you by the time you finish reading this.
// Create File System Object
var fso = new ActiveXObject( "Scripting.FileSystemObject" );
// variable to hold folder and file names
var msg = "";
// call the function scandir - passing it the
// directory where we want to start the scan
scandir( "g:\\programs" );
// Function to scan directory
function scandir( dir )
{
// Get Current Folder
var srcFolder = fso.GetFolder( dir );
msg += "Folder: " + srcFolder.Name + "\n";
// Get Files in current directory
var files = new Enumerator( srcFolder.files );
// Loop through files
for(; !files.atEnd(); files.moveNext() )
{
// You have access to each file one at a time
// in an entire directory tree. Here we grab
// the files name and add to our message variable
msg += files.item().Name + "\n";
}
// Display the data get gathered. (Folder Name and Files)
WScript.Echo( msg );
// Clear the variable for the next directory
msg = "";
// Get any sub folders to current directory
var esub = new Enumerator( srcFolder.SubFolders );
// Loop through sub folder list and scan
// through a recursive call to this function
for(; !esub.atEnd(); esub.moveNext() )
{
var f = fso.GetFolder( esub.item() );
scandir( f );
}
}
var fso = new ActiveXObject( "Scripting.FileSystemObject" );
Create a FileSystemObject so that we can access folders and files through
WSH.
var msg = "";
In order to demonstrate moving through a directory tree, we are going to
capture the folder name and the name of each file the folder contains. Later
in the script we will display this information to the user.
scandir( "g:\\programs" );
Call the function scandir passing to it the folder of
where we want to start our scan.
var srcFolder = fso.GetFolder( dir );
In order to do anything really useful with the FileSystemObject,
which we created as fso, we need to call some of its methods.
In this case we need to get a pointer to the current directory we
are looking at. dir is the variable that contains the folder path
and name passed to the function scandir( dir ).
msg += "Folder: " + srcFolder.Name + "\n";
Next, we grab the name of the folder and store it in our data
collection variable, which is used to build the output msg. Since
you have a pointer to a folder you can, in your scripts, access any
of the folder properties.
var files = new Enumerator( srcFolder.files );
We also want to get the names of each of the files in a folder. This
data is stored in a collection contained within our object srcFolder.
In JScript, we need to convert this collection into an Enumerator Object
to work with it.
for(; !files.atEnd(); files.moveNext() )
{
msg += files.item().Name + "\n";
}
We construct a basic for loop to move through the enumerator.
The method atEnd() return true if we are at the end of the
collection, which will terminate this loop. A call to moveNext
takes us through the collection, item by item. Calling the enumerator
method item() returns the current item in the collection, in this case
the file. To make things a little cleaner, we access the name property
all in a single call.
We could have written the body of the for loop like this.
var currentFile = files.item();
var CurrentFileName = currentFile.Name;
msg += CurrentFileName + "\n";
WScript.Echo( msg );
msg = "";
The first line shows the user the data we collected, which will contain the
folder name and the files it contains. The second line sets our variable back
to nothing before we move to the next folder.
var esub = new Enumerator( srcFolder.SubFolders );
for(; !esub.atEnd(); esub.moveNext() )
{
var f = fso.GetFolder( esub.item() );
scandir( f );
}
Up until until now, we have addressed the current folder's name and the files
that it contains. We have not taken a look at any possible sub folders. We
do this exactly like we did when we enumerated the 'files' collection. The
only difference is that we pass srcFolder.SubFolders to the enumerator
constructor.
esub contains the folder names of any sub folder to
the directory we are currently pointed to with srcFolder. If no
sub folders exist, esub is an 'empty' object.
Assuming there are sub folders, we enter the body of the for loop. Once inside
we grab get the current folders name and path and store it in var f.
Next, we made a recursive call to scandir() passing each subfolder
path and name. The very first call to scandir identified the folder
to start with. Subsequent calls to scandir() handle any and all
sub folders, one by one.
- When using recursion, ensure that you use the var statement when
declaring variables. This ensures that you are working with the correct data.
Try removing the var statements from the example and you will see a
very different result.
- Improperly implemented recursion can lead to an infinite loop( bad ). If
you run into this when writing your scripts, you will typically have to 'kill'
WSH (wscript.exe or cscript.exe) through the task manager. Whe debuggin your
scripts, pay particular attention to any loops that you are using, and ensure
that they have a way to exit.
Copyright 1999 Daren Thiel - www.winscripter.com