| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 | /******************************************************************************* copyright: Copyright (c) 2004 Kris Bell. All rights reserved license: BSD style: $(LICENSE) version: Jun 2004: Initial release version: Dec 2006: Pacific release author: Kris *******************************************************************************/ module tango.io.FileScan; public import tango.io.FilePath; private import tango.core.Exception; pragma(msg, "tango.io.FileScan is deprecated. Please use tango.io.FilePath.toList or tango.io.vfs.* instead."); deprecated: /******************************************************************************* This module is deprecated because it doesn't support file globbing or regexes for matching files and because it ignores folders that it doesn't recurse into (a non-recursive scan will never return any folders). Recursively scan files and directories, adding filtered files to an output structure as we go. This can be used to produce a list of subdirectories and the files contained therein. The following example lists all files with suffix ".d" located via the current directory, along with the folders containing them: --- auto scan = new FileScan; scan (".", ".d"); Stdout.formatln ("{} Folders", scan.folders.length); foreach (folder; scan.folders) Stdout.formatln ("{}", folder); Stdout.formatln ("\n{} Files", scan.files.length); foreach (file; scan.files) Stdout.formatln ("{}", file); --- This is unlikely the most efficient method to scan a vast number of files, but operates in a convenient manner. *******************************************************************************/ class FileScan { alias sweep opCall; FilePath[] fileSet; const(char)[][] errorSet; FilePath[] folderSet; /*********************************************************************** Alias for Filter delegate. Accepts a FilePath & a bool as arguments and returns a bool. The FilePath argument represents a file found by the scan, and the bool whether the FilePath represents a folder. The filter should return true, if matched by the filter. Note that returning false where the path is a folder will result in all files contained being ignored. To always recurse folders, do something like this: --- return (isDir || match (fp.name)); --- ***********************************************************************/ alias FilePath.Filter Filter; /*********************************************************************** Return all the errors found in the last scan ***********************************************************************/ public const(char)[][] errors () { return errorSet; } /*********************************************************************** Return all the files found in the last scan ***********************************************************************/ public FilePath[] files () { return fileSet; } /*********************************************************************** Return all directories found in the last scan ***********************************************************************/ public FilePath[] folders () { return folderSet; } /*********************************************************************** Sweep a set of files and directories from the given parent path, with no filtering applied ***********************************************************************/ FileScan sweep (const(char)[] path, bool recurse=true) { return sweep (path, cast(Filter) null, recurse); } /*********************************************************************** Sweep a set of files and directories from the given parent path, where the files are filtered by the given suffix ***********************************************************************/ FileScan sweep (const(char)[] path, const(char)[] match, bool recurse=true) { return sweep (path, (FilePath fp, bool isDir) {return isDir || fp.suffix == match;}, recurse); } /*********************************************************************** Sweep a set of files and directories from the given parent path, where the files are filtered by the provided delegate ***********************************************************************/ FileScan sweep (const(char)[] path, Filter filter, bool recurse=true) { errorSet = null, fileSet = folderSet = null; /* Bad dup */ return scan (new FilePath(path.dup), filter, recurse); } /*********************************************************************** Internal routine to locate files and sub-directories. We skip entries with names composed only of '.' characters. ***********************************************************************/ private FileScan scan (FilePath folder, Filter filter, bool recurse) { try { auto paths = folder.toList (filter); auto count = fileSet.length; foreach (path; paths) if (! path.isFolder) fileSet ~= path; else if (recurse) scan (path, filter, recurse); // add packages only if there's something in them if (fileSet.length > count) folderSet ~= folder; } catch (IOException e) errorSet ~= e.toString(); return this; } } /******************************************************************************* *******************************************************************************/ debug (FileScan) { import tango.io.Stdout; void main() { auto scan = new FileScan; scan ("."); Stdout.formatln ("{} Folders", scan.folders.length); foreach (folder; scan.folders) Stdout (folder).newline; Stdout.formatln ("\n{} Files", scan.files.length); foreach (file; scan.files) Stdout (file).newline; Stdout.formatln ("\n{} Errors", scan.errors.length); foreach (error; scan.errors) Stdout (error).newline; } } |