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