Globbing in Igor Pro

Glob returns the path names of all objects matching pattern as a text wave, where "objects" means waves, global variables, global string and data folders.

  • * can match any string of characters not containing :
  • ** matches any string of characters containing :

Examples

+ root (current folder)
 + folder1
 + subfolder1
  - V_flag
 - subfolder2
 + folder2
  - subfolder1
  - subfolder2

glob("root:folder*") //-> {"root:folder1", "root:folder2"}
glob("root:**1") //-> {"root:folder1", "root:folder1:subfolder1", "root:folder2:subfolder1"}
glob(":**:V_flag") // -> {":folder1:subfolder1:V_flag"}

Code

#pragma rtGlobals=3     // Use modern global access method and strict wave access.
#pragma ModuleName = glob
#pragma version = 0.1

Function/WAVE glob(pattern)
    String pattern
   
    if(StringMatch(pattern, "root:*")) // absolute path
        WAVE/T buffer = glob_("root:", pattern[5, inf])
    elseif(StringMatch(pattern, ":*")) // relative path (beginning with :)
        WAVE/T buffer = glob_(":", pattern[1, inf])
    else // relative path (others)
        WAVE/T buffer = glob_("", pattern) 
        buffer = (buffer)[1, inf] // glob_ adds : to represent a relative path
    endif
   
    // glob does not add ending : for folders unless the user adds :
    if(StringMatch(pattern "*:"))
        buffer = RemoveEnding(buffer, ":") + ":"
    endif
   
    return buffer
End

// Returns a text wave containing matched pathnames
static Function/WAVE glob_(root, pattern)
    String root    // a relative or absolute pathname as a root
    String pattern // a maching pattern using * or **
   
    // the root pathname must end with :
    root = RemoveEnding(root, ":") + ":"

    Make/FREE/T/N=0 buffer
       
    // leaf / inner node of matching algorithm
    if(ItemsInList(pattern, ":") < 2)
        // leaf node of matching algorithm
       
        // data folder only or not
        if(StringMatch(pattern, "*:"))
            Concatenate/T/NP {MatchedFolders(root, RemoveEnding(pattern, ":"))}, buffer
        else
            Concatenate/T/NP {MatchedObjects(root, pattern), MatchedFolders(root, pattern)}, buffer
        endif

    else
        // inner node of matching algorithm
       
        // refers a parent folder (using ::) or not
        if(StringMatch(pattern, ":*"))
            // matching with a parent path
           
            root += SelectString(StringMatch(root, "root:"), ":", "") // the root of root: is root: itself         
            Concatenate/T/NP {glob_(root, pattern[1, inf])}, buffer                
       
        else
            // matching recursively
           
            WAVE/T folders = MatchedFolders(root, StringFromList(0, pattern, ":"))
            Variable i
            for(i = 0; i < DimSize(folders, 0); i += 1)
                Concatenate/T/NP {glob_(folders[i], pattern[strsearch(pattern, ":", 0)+1, inf])}, buffer
            endfor
       
        endif      
    endif
   
    // global matching pattern ** is equivalent to *:**
    if(strsearch(StringFromList(0, pattern, ":"), "**", 0) >= 0)
        Concatenate/T/NP {glob_(root, ReplaceString("**", pattern, "*:**", 0, 1))}, buffer
    endif  
   
    return buffer      
End

static Function/WAVE MatchedFolders(root, pattern)
    String root, pattern
    root = RemoveEnding(root, ":") + ":"

    Make/FREE/T/N=(DataFolderExists(root) ? CountObjects(root, 4) : 0) folders = PossiblyQuoteName(GetIndexedObjName(root, 4, p))
    Extract/T/O folders, folders, Match(folders, pattern)
    folders = root + folders
   
    return folders
End

static Function/WAVE MatchedObjects(root, pattern)
    String root, pattern
    root = RemoveEnding(root, ":") + ":"
   
    Make/FREE/T/N=(DataFolderExists(root) ? CountObjects(root, 1) : 0) wavs = GetIndexedObjName(root, 1, p)
    Make/FREE/T/N=(DataFolderExists(root) ? CountObjects(root, 2) : 0) vars = GetIndexedObjName(root, 2, p)
    Make/FREE/T/N=(DataFolderExists(root) ? CountObjects(root, 3) : 0) strs = GetIndexedObjName(root, 3, p)

    Make/FREE/T/N=0 objects
    Concatenate/T/NP {wavs, vars, strs}, objects
   
    Extract/T/O objects, objects, Match(objects, pattern)
    objects = root + objects
   
    return objects
End

static Function Match(str, pattern)
    String str, pattern
    // A pattern matches both of normal a name and a free name.
    // For example, "*1" matches both of "folder1" and "'folder 1'"
    //
    // If a pattern is beginning with !, the return value of StringMatch is reveresed.
    // Because ! has no meaning for the pathname-matching, compare (" " + str) with (" " + pattern) here.
   
    if(StringMatch(str, "'*'"))
        return StringMatch(" " + RemoveEnding(str[1, inf], "'"), " " + pattern) || StringMatch(" " + str, " " + pattern)
    else
        return StringMatch(" " + str, " " + pattern)
    endif  
End

Forum

Support

Gallery

Igor Pro 8

Learn More

Igor XOP Toolkit

Learn More

Igor NIDAQ Tools MX

Learn More