Question
Tony Alexander · Nov 22

How to lists all files in a given folder (and sub-folders if needed)

Hi Community,

I recently needed to interrogate some folders/sub-folders to retrieve filenames using cache object script(COS) and I implemented it in the following way.

ClassMethod ListDir(
               path = "",
               wildchar = "*",
               recursive As %String(VALUELIST=",y,n") = "y",
               ByRef dirlist)
{
               i path'=""{
                              i ##class(%File).DirectoryExists(path){
                                             s rs=##class(%ResultSet).%New("%File:FileSet")
                                             s sc=rs.Execute(path,wildchar,"",1)
                                             while(rs.Next()){
                                                            s name=rs.Data("Name")
                                                            s type=rs.Data("Type")
                                                            // if sub-folder loop once more
                                                            i type="D",recursive="y"{
                                                                           d ..ListDir(name,wildchar,"y",.dirlist)
                                                            }
                                                            // if file add to list
                                                            i type="F"{
                                                                           s dirlist($i(dirlist))=name
                                                            }
                                             }
                                             d rs.Close()
                              }
               }
}

The code passes the output as an array (dirlist). Setting the recursive flag to "y" will loop through individual sub-folders and providing a value for wild-char will restrict the result to your desired extension. Pretty sure there's probably a better way to do this, but this worked for me and results are returned fairly quickly. I hope you find it useful.

Product version: Caché 2018.1
$ZV: Cache for Windows (x86-64) 2018.1.1 (Build 312U)
40
2 0 8 216
Log in or sign up to continue

There is a ready-made method for this: getFileslink

Usage example:

path="C:\Temp"

pExtension=1
pExtension(1)="*"

pTempNode=$i(^CacheTemp)
^CacheTemp(pTempNode)
   
##class(%SQL.Util.Import).getFiles(path,.pExtension,pTempNode,1)
dirlist=^CacheTemp(pTempNode)
^CacheTemp(pTempNode)

zw dirlist

This looks like an excellent resource and I hadn't heard of it before.  Thank you so much for sharing!

This (getFiles) method is marked as internal in Cache, and yes, it's typical internal as it's usage is relied on the strong internals knowledge :). Besides, it's hidden in IRIS, and its caller should be rewritten to achieve DBMS independence:

ClassMethod ListDir2(path = "", wildchar = "*", recursive As %String(VALUELIST=",y,n") = "y", ByRef dirlist)
{
 pExtension=1
 pExtension(1)=wildchar

#if $zversion["IRIS"
 temp=$name(^IRIS.Temp)
#else
 temp=$name(^CacheTemp)
#endif
 
 pTempNode=$i(@temp)
 @temp@(pTempNode)
   
 ##class(%SQL.Util.Import).getFiles(path,.pExtension,pTempNode,recursive="y")
 dirlist=@temp@(pTempNode)
 @temp@(pTempNode)  ;zw dirlist
}

I guess I re-invented the wheel a bit, thanks for the info.

Don't worry about it - I have been writing ObjectScript code for 18 years and I had no idea about this method - I have always done it the way you did in your example :)  Thanks for asking the question so I could learn something new as well!

@Tony Alexander,
your method is ~30% faster then "ready made" on the directory tree populated with ~ 200 files.
Keep re-inventing wheels!

For those MUMPS veterans. you can also use the $ZSEARCH function. As in the example:

  NEW $NAMESPACE
  SET $NAMESPACE="USER"
  SET file=$ZSEARCH("i*")
   WHILE file'="" {
       WRITE !,file
       SET file=$ZSEARCH("")
   }
   WRITE !,"That is all the matching files"
   QUIT

I think this one will be faster

I hadn't heard of that %SQL method either and, as well as speed, the %File method has advantages such as more file details being returned and better filtering with wildcards.