1 /******************************************************************************* 2 3 copyright: Copyright (c) 2004 Kris Bell. All rights reserved 4 5 license: BSD style: $(LICENSE) 6 7 version: Jun 2004: Initial release 8 version: Dec 2006: Pacific release 9 10 author: Kris 11 12 *******************************************************************************/ 13 14 module tango.io.FileScan; 15 16 17 18 public import tango.io.FilePath; 19 20 private import tango.core.Exception; 21 22 pragma(msg, "tango.io.FileScan is deprecated. Please use tango.io.FilePath.toList or tango.io.vfs.* instead."); 23 24 deprecated: 25 26 /******************************************************************************* 27 This module is deprecated because it doesn't support file globbing 28 or regexes for matching files and because it ignores folders that 29 it doesn't recurse into (a non-recursive scan will never return any 30 folders). 31 32 Recursively scan files and directories, adding filtered files to 33 an output structure as we go. This can be used to produce a list 34 of subdirectories and the files contained therein. The following 35 example lists all files with suffix ".d" located via the current 36 directory, along with the folders containing them: 37 --- 38 auto scan = new FileScan; 39 40 scan (".", ".d"); 41 42 Stdout.formatln ("{} Folders", scan.folders.length); 43 foreach (folder; scan.folders) 44 Stdout.formatln ("{}", folder); 45 46 Stdout.formatln ("\n{} Files", scan.files.length); 47 foreach (file; scan.files) 48 Stdout.formatln ("{}", file); 49 --- 50 51 This is unlikely the most efficient method to scan a vast number of 52 files, but operates in a convenient manner. 53 54 *******************************************************************************/ 55 56 class FileScan 57 { 58 alias sweep opCall; 59 60 FilePath[] fileSet; 61 const(char)[][] errorSet; 62 FilePath[] folderSet; 63 64 /*********************************************************************** 65 66 Alias for Filter delegate. Accepts a FilePath & a bool as 67 arguments and returns a bool. 68 69 The FilePath argument represents a file found by the scan, 70 and the bool whether the FilePath represents a folder. 71 72 The filter should return true, if matched by the filter. Note 73 that returning false where the path is a folder will result 74 in all files contained being ignored. To always recurse folders, 75 do something like this: 76 --- 77 return (isDir || match (fp.name)); 78 --- 79 80 ***********************************************************************/ 81 82 alias FilePath.Filter Filter; 83 84 /*********************************************************************** 85 86 Return all the errors found in the last scan 87 88 ***********************************************************************/ 89 90 public const(char)[][] errors () 91 { 92 return errorSet; 93 } 94 95 /*********************************************************************** 96 97 Return all the files found in the last scan 98 99 ***********************************************************************/ 100 101 public FilePath[] files () 102 { 103 return fileSet; 104 } 105 106 /*********************************************************************** 107 108 Return all directories found in the last scan 109 110 ***********************************************************************/ 111 112 public FilePath[] folders () 113 { 114 return folderSet; 115 } 116 117 /*********************************************************************** 118 119 Sweep a set of files and directories from the given parent 120 path, with no filtering applied 121 122 ***********************************************************************/ 123 124 FileScan sweep (const(char)[] path, bool recurse=true) 125 { 126 return sweep (path, cast(Filter) null, recurse); 127 } 128 129 /*********************************************************************** 130 131 Sweep a set of files and directories from the given parent 132 path, where the files are filtered by the given suffix 133 134 ***********************************************************************/ 135 136 FileScan sweep (const(char)[] path, const(char)[] match, bool recurse=true) 137 { 138 return sweep (path, (FilePath fp, bool isDir) 139 {return isDir || fp.suffix == match;}, recurse); 140 } 141 142 /*********************************************************************** 143 144 Sweep a set of files and directories from the given parent 145 path, where the files are filtered by the provided delegate 146 147 ***********************************************************************/ 148 149 FileScan sweep (const(char)[] path, Filter filter, bool recurse=true) 150 { 151 errorSet = null, fileSet = folderSet = null; 152 /* Bad dup */ 153 return scan (new FilePath(path.dup), filter, recurse); 154 } 155 156 /*********************************************************************** 157 158 Internal routine to locate files and sub-directories. We 159 skip entries with names composed only of '.' characters. 160 161 ***********************************************************************/ 162 163 private FileScan scan (FilePath folder, Filter filter, bool recurse) 164 { 165 try { 166 auto paths = folder.toList (filter); 167 168 auto count = fileSet.length; 169 foreach (path; paths) 170 if (! path.isFolder) 171 fileSet ~= path; 172 else 173 if (recurse) 174 scan (path, filter, recurse); 175 176 // add packages only if there's something in them 177 if (fileSet.length > count) 178 folderSet ~= folder; 179 180 } catch (IOException e) 181 errorSet ~= e.toString(); 182 return this; 183 } 184 } 185 186 187 /******************************************************************************* 188 189 *******************************************************************************/ 190 191 debug (FileScan) 192 { 193 import tango.io.Stdout; 194 195 void main() 196 { 197 auto scan = new FileScan; 198 199 scan ("."); 200 201 Stdout.formatln ("{} Folders", scan.folders.length); 202 foreach (folder; scan.folders) 203 Stdout (folder).newline; 204 205 Stdout.formatln ("\n{} Files", scan.files.length); 206 foreach (file; scan.files) 207 Stdout (file).newline; 208 209 Stdout.formatln ("\n{} Errors", scan.errors.length); 210 foreach (error; scan.errors) 211 Stdout (error).newline; 212 } 213 }