FindOnClick V3 introduced a powerful new feature: scripting. Scripting lets the user define exactly what files and/or folders to include in the search results. Although FindOnClick already provides the user with numerous advanced filtering options, with scripting you can extend that with almost limitless flexibility. The scripting language used in FindOnClick is the same as the Pascal scripting available in SyncBackPro.
Scripting is a way in which the searching functionality of FindOnClick can be changed or extended by writing a small script. A script is a set of instructions and is similar to the macro support in Microsoft Office and Java Script in web pages. It is also similar to plug-ins in other software. FindOnClick can use scripts written in Pascal.
In simple terms, FindOnClick calls defined functions in a script for each file/folder that has been found (and not already filtered out by the search settings). When the functions are called, data about the file/folder is given to the script function, e.g. the filename, size, attributes, etc. The functions can then decide if the file/folder should be filtered out or not.
For each drive (or path) that FindOnClick must search, it has a two-stage search:
First, it gets a list of the files and folders. Those files/folders are then filtered using the search settings. For example, you may have search settings that say you only want files over 100MB that have been modified today. Any files and folders that do not match those search settings are filtered out from the search results. This is repeated for each drive/path that needs to be searched.
Once all the drives/paths have been searched, it then performs post-processing on the resulting files and folders. The second stage (post-processing) is optional, depending on the search settings. A second stage is only required when something needs to be done with the contents of a file, e.g. file hashing, searching the contents, getting MP3 information or retrieving the version number of a file.
With scripting you can change the search results during both stages. So, in summary:
With scripting, we can change the search results. For each file & folder, that has not already been filtered out by the search results, FindOnClick calls the script. The script can then decide to filter out the item or not. This is achieved by having a script that defines certain functions. All of the functions are optional, depending on how you want the script filtering to be performed.
Script functions are called in this order (and all are optional, i.e. they don't need to be defined in the script):
As mentioned, all the functions are optional. For example, you may not care if the search has completed, so there is no need to include the function SearchEnd in your script. You may only want to do post-processing, so many of the other functions may not be required.
The OnClick Help File explains in detail what each of the functions are for and how they are used.
With just the basic Pascal scripting language, a script would be limited in what it could do. So to help a script be more functional, FindOnClick provides a number of supporting functions and classes. For example, a number of functions are available to the script to manipulate filenames, compare dates & times, use regular expressions, etc.
Scripts can also use COM objects and DLL's, meaning that functions provided by Windows (or other programs, utilities or developed by yourself) can be used.
The OnClick Help File explains in detail the support functions, classes, constants, etc. are available to scripts.
Scripting has an impact on search performance. Small, simple scripts may slightly increase search time, but complex scripts can significantly increase the search time. This is unavoidable as processing a script is a non-trivial task. However, there are things you can do in the script to reduce the impact:
Loading a script is simple:
While editing a script you can edit it and save the changes. Pressing F9, while editing a script, compiles it. Compilation makes sure the script doesn't have any obvious mistakes.
FindOnClick comes with a number of simple example scripts. For example, SameNameAsParent.pas:
// // Only include files that have the same name as their parent folder, e.g. // // C:\abc\def\def will return TRUE, because the filename 'def' is the same name as the parent folder // C:\abc\def\ghi will return FALSE // function Include(fname, DOSfname, fsize, fattrs, fcreate, faccess, fmod, fstreams, fhash, fver); begin if (fattrs and FILE_ATTRIBUTE_DIRECTORY = 0) then Result:=SameStr(ExtractFileName(ExtractFileDir(fname)), ExtractFileName(fname)) else Result:=FALSE; end;
This very simple script shows how to filter based on the filename. First, it checks to see if the item is a file or a folder (fattrs and FILE_ATTRIBUTE_DIRECTORY = 0). If it's a file (because it does not have the FILE_ATTRIBUTE_DIRECTORY file system attribute) then we see if it's filename is the same as the name of the folder the file is in. If not, then FALSE is returned (meaning it is filtered out). If it's a folder, then it is filtered out (Result:=FALSE).
Another slightly more complex example script is OldestFile.pas:
// // This script will look for the oldest file or folder (based on last modification date & time) // var OldestFile; function Include(fname, DOSfname, fsize, fattrs, fcreate, faccess, fmod, fstreams, fhash, fver); begin Result:=(CompareDateTime(fmod, OldestFile) = LessThanValue); if Result then OldestFile:=fmod; end; // Tell FindOnClick to call PostInclude function DoPostFiltering; begin Result:=TRUE; end; function PostInclude(fname, DOSfname, fsize, fattrs, fcreate, faccess, fmod, fstreams, fhash, fver); begin Result:=(CompareDateTime(fmod, OldestFile) = EqualsValue); end; procedure SearchBegin(SearchPath, IsSlowSearch); begin if not Assigned(OldestFile) then OldestFile:=Now; end;
This script introduces more concepts:
MostFiles.pas shows how to use PostIncludeEx and TFileList to keep track of many values:
// // This script will list the folders that contain the most child folders and files // var FList: TFileList; function Include(fname, DOSfname, fsize, fattrs, fcreate, faccess, fmod, fstreams, fhash, fver); begin FList.AddInc(ExtractParentDirectory(fname)); end; // Give FindOnClick a list of names function PostIncludeEx(var FilterList); begin FList.RemoveNotValue(FList.Highest); FilterList:=FList; Result:=TRUE; end; procedure SearchBegin(SearchPath, IsSlowSearch); begin if not Assigned(FList) then FList:=TFileList.Create(EFLT_FullPath) else // We must now be searching the second, third, etc. drive/path // So remove entries that cannot be included now before we continue the search FList.RemoveNotValue(FList.Highest); end; procedure SearchEnd; begin FList.Free; end;
This script introduces more concepts:
The addition of scripting into FindOnClick introduces new possibilities to find exactly the files and folders you need to find.