[xplorer˛] — Search for files with scripts
home » blog » 21 February 2010 [programming]
 

Once upon a time people played pacman and used MSDOS and command line tools to manage their files. Now we have playstations and xplorer˛, respectively. But not everything can be done within xplorer˛; I've been asked the other day, How can I find files with extremely long filenames? You can't do this in xplorer˛ yet, as there is no column (property) with the length of a filename in characters that can be used with the <Ctrl+F> find command.

One far-fetched possibility is to write a column handler that lists the length of filenames, which will be integrated with xplorer˛. A much simpler approach is to hack a visual basic script to read the contents of the folder we want to scan. One year ago I wrote an introduction to WSH that perhaps wasn't focused enough. So today we will write a small script to search for files under a folder.

Hack your first windows script

File management scripts are similar to the CMD/BAT files of yestercentury, only they resemble more a programming language, as many of you who write scripts for webpages will know. I prefer visual basic scripts (VBS), which are like the macros we write in Excel. Plain text VBS files can be written in notepad or if you want frills like autocompletion you can use a script IDE.

REM DIR.VBS: get a listing of all contents in some folder
what = "C:\TEMP"

Set oFSO = CreateObject("Scripting.FileSystemObject")
Set oDir = oFSO.GetFolder(what)

For Each f in oDir.Files
   Wscript.Echo what & "\" & f.name
Next

For Each f in oDir.subfolders
   Wscript.Echo what & "\" & f.name
Next

Save this listing as DIR.VBS, open a command line prompt (e.g. Start > Run > CMD.EXE; in xplorer˛ just type $ in the addressbar), switch to the folder you saved your script and type cscript DIR.VBS to run the script. It will show all the contents of C:\TEMP folder, one full file path per line. For those of you still with us and reading <g> this basic script combines a few programming elements: run

  • Program statements. We have all sorts of visual basic elements like variables (what), loops (For Each - Next) etc. Lines that start with REM are comments.
     
  • Scriptable objects. Scripts are infinitely extensible through objects like FileSystemObject that add extra capabilities. We used the GetFolder method to open a folder, which was returned as a new Folder object. We used the Files and Subfolders collections of the folder object to read the contained files and subfolders respectively. Finally we got the filename using the Name property.
     
  • WScript objects. A subset of scriptable objects are available without explicit creation like the WScript object which we used to write (Echo) the filename. We also used the visual basic string concatenation operator '&' to merge the folder path and the filename.
     

Recurse into subfolders

A basic search operation is to enter subfolders. When reading a folder you come across a subfolder, you want to read inside it too. Which may lead you to further subfolders even deeper down and you want to enter these too, all the way down. We will modify our basic script so that it contains a subroutine to scan a folder, which will call itself whenever it encounters a subfolder. That's the well known principle of recursion. Type and save the following listing as SUBDIR.VBS:

REM SUBDIR.VBS: get a recursive listing a folder
call listdir("C:\TEMP")

Sub listDir(what)
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set oDir = oFSO.GetFolder(what)

For Each f in oDir.Files
   Wscript.Echo what & "\" & f.name
Next

' recursively enter subfolders
For Each f in oDir.subfolders
   call listdir(what & "\" & f.name)
Next
end sub

If you compare this with the earlier script, you'll see that the former script was turned into a subroutine called LISTDIR, delimited with the visual basic SUB and END SUB statements. We use the CALL statement to execute the subroutine from the main script using the root folder name C:\temp. Our LISTDIR subroutine accepts the name of the folder to scan, a variable called what as before.

The real trick is that for subfolders, we call ourselves with the deep folder name: we compose the full path to the subfolder and pass it as an argument to ourselves to show its contents:
call listdir(what & "\" & f.name)

File search criteria

Our script can already list all the files in our folders and subfolders. Instead of printing the name of all files, we want to search for something in particular, files with long names. Here is the final search script:

REM SEARCH.VBS: scan a folder for long filenames
call listdir("C:\TEMP")

Sub listDir(what)
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set oDir = oFSO.GetFolder(what)

For Each f in oDir.Files
   ' only print the names of long files
   if Len(f.name) > 100 then
      Wscript.Echo what & "\" & f.name
   end if
Next

' recursively enter subfolders
For Each f in oDir.subfolders
   call listdir(what & "\" & f.name)
Next
end sub

This listing is almost identical, except for the contitional IF statement in the file reading loop. We use visual basic's Len function to get the length of the filename and we only print it if it is larger than 100 characters long. So only long filenames will be 'found' when you run this script from a command prompt (cscript SEARCH.VBS).

For fun and practice you can extend this searching script to find only files with particular attributes, e.g. whose size is larger than 1MB. Hint: look into the methods of File object to see what you can use (that Size property looks useful :)

ps. If you already have microsoft office or developer studio you can use the MSE script editor after some tweaks to edit VBS scripts. This way you get method and property autocompletion for the various filesystem objects above

Post a comment on this topic

 

 

What would you like to do next?

Reclaim control of your files!
  • browse
  • preview
  • manage
  • locate
  • organize
Download xplorer2 free trial
"This powerhouse file manager beats the pants off Microsoft's built-in utility..."

download.com
© 2002—2010 Nikos Bozinis, all rights reserved