#FEATURE by cg
authorClaus Gittinger <cg@exept.de>
Thu, 20 Oct 2016 16:11:30 +0200
changeset 20686 ea3d093f028d
parent 20685 4cf48622d541
child 20687 7bd162e55581
#FEATURE by cg class: Filename added: #recursiveDirectoryContentsAsFilenamesDo:filterForVisitingDirectories: #recursiveDirectoryContentsDo:filterForVisitingDirectories: #recursiveDirectoryContentsWithPrefix:filesDo:directoriesDo:filterForVisitingDirectories: changed: #recursiveDirectoryContentsWithPrefix:filesDo:directoriesDo: new protocol to enumerate deep, but skip (dont enter) individual folders, based on a filter (allows skipping subfolders like ".deleted", ".attic" etc.
Filename.st
--- a/Filename.st	Wed Oct 19 12:50:48 2016 +0200
+++ b/Filename.st	Thu Oct 20 16:11:30 2016 +0200
@@ -2522,6 +2522,30 @@
     "Modified: / 12-09-2010 / 15:43:22 / cg"
 !
 
+recursiveDirectoryContentsAsFilenamesDo:aBlock filterForVisitingDirectories:filterOrNil
+    "evaluate aBlock for all files and directories found under the receiver.
+     The block is invoked with the filenames as argument.
+     The walk is bread-first.
+     This excludes any entries for '.' or '..'.
+     Subdirectory files are included with a relative pathname.
+     If filterOrNil is nonNil, it is passed every directory about to be walked into;
+     if it returns false, that directory is not entered.
+     Warning: this may take a long time to execute 
+     (especially with deep and/or remote fileSystems)."
+
+    self 
+        recursiveDirectoryContentsDo:[:relFn |
+            aBlock value:(self construct:relFn)
+        ]
+        filterForVisitingDirectories:filterOrNil.
+
+    "
+     '.' asFilename recursiveDirectoryContentsAsFilenamesDo:[:f | Transcript showCR:f]
+    "
+
+    "Modified: / 12-09-2010 / 15:43:22 / cg"
+!
+
 recursiveDirectoryContentsDo:aBlock
     "evaluate aBlock for all files and directories found under the receiver.
      The block is invoked with the relative filenames as string-argument.
@@ -2562,13 +2586,64 @@
     "
 !
 
+recursiveDirectoryContentsDo:aBlock filterForVisitingDirectories:filterOrNil
+    "evaluate aBlock for all files and directories found under the receiver.
+     The block is invoked with the relative filenames as string-argument.
+     The walk is bread-first.
+     This excludes any entries for '.' or '..'.
+     Subdirectory files are included with a relative pathname.
+     If filterOrNil is nonNil, it is passed every directory about to be walked into;
+     if it returns false, that directory is not entered.
+     Warning: this may take a long time to execute 
+     (especially with deep and/or remote fileSystems)."
+
+    self 
+        recursiveDirectoryContentsWithPrefix:'' 
+        filesDo:aBlock 
+        directoriesDo:aBlock
+        filterForVisitingDirectories:filterOrNil    
+
+    "
+     '.' asFilename recursiveDirectoryContentsDo:[:f | Transcript showCR:f]
+    "
+
+    "Modified: / 12-09-2010 / 15:43:22 / cg"
+!
+
 recursiveDirectoryContentsWithPrefix:aPrefix filesDo:fileBlock directoriesDo:dirBlock
     "evaluate aBlock for all files and directories found under the receiver.
      The blocks are invoked with a relative pathname as string-argument.
      The walk is breadth-first (first files, then directories).
      This excludes any entries for '.' or '..'.
      A proceedable exception is raised for non-accessible directories.
-     Warning: this may take a long time to execute (especially with deep and/or remote fileSystems)."
+     Warning: this may take a long time to execute 
+     (especially with deep and/or remote fileSystems)."
+
+    self
+        recursiveDirectoryContentsWithPrefix:aPrefix 
+        filesDo:fileBlock 
+        directoriesDo:dirBlock
+        filterForVisitingDirectories:nil
+
+    "
+     '.' asFilename 
+        recursiveDirectoryContentsWithPrefix:'bla'
+        filesDo:[:f | Transcript show:'file: '; showCR:f]
+        directoriesDo:[:f | Transcript show:'dir: '; showCR:f]
+    "
+!
+
+recursiveDirectoryContentsWithPrefix:aPrefix filesDo:fileBlock directoriesDo:dirBlock filterForVisitingDirectories:filterOrNil
+    "evaluate aBlock for all files and directories found under the receiver.
+     The blocks are invoked with a relative pathname as string-argument.
+     The walk is breadth-first (first files, then directories).
+     This excludes any entries for '.' or '..'.
+     A proceedable exception is raised for non-accessible directories.
+     If filterOrNil is nonNil, it is passed every directory about to be walked into;
+     if it returns false, that directory is not entered.
+     Warning: this may take a long time to execute 
+     (especially with deep and/or remote fileSystems).
+    "
 
     |fileNames dirNames p|
 
@@ -2579,9 +2654,11 @@
     self directoryContentsDo:[:f | |t|
         t := self construct:f.
         t isDirectory ifTrue:[
-            dirBlock notNil ifTrue:[
-                t isSymbolicLink ifFalse:[
-                    dirNames add:f
+            (filterOrNil isNil or:[filterOrNil value:t]) ifTrue:[
+                dirBlock notNil ifTrue:[
+                    t isSymbolicLink ifFalse:[
+                        dirNames add:f
+                    ]
                 ]
             ]
         ] ifFalse:[
@@ -2602,10 +2679,15 @@
     ].
     dirBlock notNil ifTrue:[
         dirNames do:[:dN |
-            dirBlock value:(p , dN).
-            (self construct:dN)
-                recursiveDirectoryContentsWithPrefix:(p , dN) 
-                filesDo:fileBlock directoriesDo:dirBlock
+            |subDir|
+
+            subDir := (self construct:dN).
+            (filterOrNil isNil or:[filterOrNil value:subDir]) ifTrue:[
+                dirBlock value:(p , dN).
+                subDir
+                    recursiveDirectoryContentsWithPrefix:(p , dN) 
+                    filesDo:fileBlock directoriesDo:dirBlock
+            ].
         ].
     ].