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;
}
}
|