Skip to content

File Pattern Matcher

thofrey edited this page Apr 1, 2014 · 8 revisions

Available in Mach-II 1.9+

Table of Contents

  1. Overview
  2. Public Methods

Overview

The MachII.util.matching.FileMatcher is a specialty utility that performs a pattern match against a group of files and filters the results. The results are a CFML query data type and has the same columns as results returned by cfdirectory (including two additional columns we're discuss more later).

In all reality, the File Pattern Matcher is a specialized version of the ANT Style Pattern Matcher that works with results from cfdirectory. This matcher is one of the main utilities that drive View Loaders that was introduced in Mach-II 1.8.

Wildcards

The utility uses three different wildcards.

Wildcard Description
* Matches zero or more characters.
? Matches exactly one character.
** Matches zero or more directories.

Example Patterns

    <tr>
        <td style="text-align: left">
            <tt>/views/products/**/*.cfm</tt>
            <br />
            <tt>.</tt>
        </td>

        <td>
            <em>Matches:</em><br />
            /views/products/index.cfm<br />
            /views/products/SE10/index.cfm<br />
            /views/products/SE10/details.cfm<br />
            /views/products/ST80/index.cfm<br />
            /views/products/ST80/details.cfm<br />
            <br />
            <em>Does Not Match:</em><br />
            /views/index.cfm<br />
            /views/aboutUs/index.cfm<br />
            /views/aboutUs/managementTeam.cfm
        </td>
    </tr>

    <tr>
        <td>
            <tt>/views/**/*.cfm</tt>
            <br />
            <tt>.</tt>
        </td>

        <td>
            <em>Matches:</em><br />
            /views/index.cfm<br />
            /views/aboutUs/index.cfm<br />
            /views/aboutUs/managementTeam.cfm<br />
            /views/products/index.cfm<br />
            /views/products/SE10/index.cfm<br />
            /views/products/SE10/details.cfm<br />
            /views/products/ST80/index.cfm<br />
            /views/products/ST80/details.cfm<br />
            <br />
            <em>Does Not Match:</em><br />
            /views/index.htm<br />
            /views/readme.txt
        </td>
    </tr>

    <tr>
        <td>
            <tt>/views/index??.cfm</tt>
            <br />
            <tt>_</tt>
        </td>

        <td>
            <em>Matches:</em><br />
            /views/index01.cfm<br />
            /views/index02.cfm<br />
            /views/indexAA.cfm<br />
            <br />
            <em>Does Not Match:</em><br />
            /views/index01.htm<br />
            /views/index1.cfm<br />
            /views/indexA.cfm<br />
            /views/indexOther.cfm<br />
            /views/anotherDir/index01.cfm<br />
            <br />
            <br />
            (Remember that `?` matches a single character, so the above example matches only files that start with "index", followed by two wildcard characters and then ".cfm".)
        </td>
    </tr>
</tbody>
Pattern / Path Separator Pattern Results

Public Methods

The init() Method

This method initializes the file pattern matcher and optionally allows you to provide a different path separator (which defaults to / if not passed) and if you want to the use the listInfo attribute for internal cfdirectory calls (typically this is more performant if you do not need information like file size or date last modified).

    <!--- Using the default path separator --->
    <cfset matcher = CreateObject("component", "MachII.util.matching.FileMatcher").init() />
Argument Name Required Default Description
pathSeparator false / Allows you to use a different path separator, but default the matcher converts all \ (Windows based file path separators) to /.
useListInfo conditional Defaults to true if your CFML engine supports this behavior Allows you to indicate if you want to use the listInfo attribute of cfdirectory for faster performance. listInfo does not return file size or date last modified. If you need this information, then set this value to false.

The isPattern() Method

This method checks if the passed path has a pattern in it by checking to see if the pattern has any *'s or ?'s in it and returns a boolean result.

Example code:

    <cfoutput>
        Is '/views/index.cfm' a pattern: #matcher.isPattern("/views/index.cfm")#</br>
        Is '/views/*.cfm' a pattern: #matcher.isPattern("/views/*.cfm")#
    </cfoutput>

Example output:

    Is '/views/index.cfm' a pattern: false
    Is '/views/*.cfm' a pattern: true

The match() Method

This is the work horse method of this utility and where all the magic happens. This method takes a pattern and a base path to start the search for matching file paths.

Argument Name Required Default Description
pattern true n/a The pattern to use for matching. This needs to be a complete absolute path or you can use a relative path from the path argument by starting your pattern with ./
path true n/a The base path directory to run a cfdirectory call against. This path cannot have any patterns in it.
removeRootPath false n/a A path to remove from the computed results. This is most useful when looking for .cfm files to be used with cfincludes as those paths cannot be absolute paths.
excludePatterns false array An array of patterns to exclude from the final results. This is useful if you want to cast a wide net with your pattern and filter those results further.

Matching Files with Absolute Path Results

This is most common if you want to match full absolute paths such as images or files on disk. If you wanted to find all .cfm files to use with cfinclude, you need to reuse the next method for relative path results.

Example code (find all .png files starting with the letter a including all files in nested directories):

    <cfset matcher = CreateObject("component", "MachII.util.matching.FileMatcher").init() />
    <cfdump var="#matcher.match("./assets/img/**/a*.png", ExpandPath("/MachII/dashboard/"))#"/>

Example output:

Image: Matching Files with Absolute Path Results

As you can see in the dump, we found all the PNG files that start with the letter a in the Mach-II Dashboard assets. Notice two additional columns in the result:

  • fullPath - This is the complete absolute path to the file.
  • modified - This is the modified path to the file. This is the same as the full path unless we supplied a removeRootPath argument in which the modifiedPath would be the full path with the remove root path taken off of it.

Matching Files with Relative Path Results

Example code (find all .cfm files starting with "snip_" including all files in nested directories):

<cfset matcher = CreateObject("component", "MachII.util.matching.FileMatcher").init() />

<cfdump var="#matcher.match("./views/**/snip_*.cfm", ExpandPath("/MachII/dashboard/"), ExpandPath("/MachII"))#"/>

Example output (partial results):

Image: Matching Files with Absolute Relative Results

As you can see in the dump, we found all the files that started with "snip_*.cfm" in the Dashboard views. Notice the modifiedPath has the value from removeRootPath from it so we can use in cfincludes:

    <cfinclude template="/MachII/#somePath#"/>

The extractPathWithoutPattern() Method

Extract the path base (the part before the pattern starts) from a string and automatically cleans the path via pathClean(). This method is useful to break a path into a base path part and a pattern part.

Example code:

    <cfoutput>
        #matcher.extractPathWithoutPattern("c:\some\random\path\**\*.cfm")#</br>
        #matcher.extractPathWithoutPattern("/a/mixed\path\of/????/**/*.xml")#
    </cfoutput>

Example output:

    c:/some/random/path/
    /a/mixed/path/of/

The pathClean() Method

This method cleans paths so all paths use a uniform delimiter of /. This delimiter is safe to use on both Windows and *nix systems.

Example code:

    <cfoutput>
        #matcher.pathClean("c:\some\random\path\index.cfm")#</br>
        #matcher.pathClean("/a/mixed\path\of/items.cfm")#
    </cfoutput>

Example output:

    c:/some/random/path/index.cfm
    /a/mixed/path/of/items.cfm
Clone this wiki locally