1 module find; 2 3 import std.file; 4 import std.path; 5 import std.range; 6 import std.regex; 7 import std.stdio; 8 import std.algorithm; 9 10 import core.exception; 11 12 import commando; 13 14 void main( string[] args ) 15 { 16 // Declare the variables for the arguments 17 bool recurse; 18 bool isRegex; 19 string directory; 20 string pattern; 21 22 try 23 { 24 // the `parse` method takes a string array and a delegate. 25 // The delegate will be used for building the parser 26 ArgumentParser.parse( args, ( ArgumentSyntax syntax ) 27 { 28 // we use `commando.CaseSensitive.yes` here because CaseSensitive conflicts with the std lib 29 syntax.config.caseSensitive = commando.CaseSensitive.yes; 30 31 // Define our options with the `option` method. 32 // The `option` method has the following signature: `void option( T )( char shortName, string longName, T* ptr, Required required, string helpText )` 33 syntax.option( 'r', "recurse", &recurse, Required.no, "Search directory recursively" ); 34 syntax.option( 'R', "regex", &isRegex, Required.no, "Specify that the pattern is a regular expression (defult is glob)" ); 35 syntax.option( 'p', "pattern", &pattern, Required.yes, "The file name search pattern" ); 36 syntax.option( 'd', "directory", &directory, Required.yes, "The directory to search" ); 37 } ); 38 } 39 catch( ArgumentParserException ex ) 40 { 41 // Catch any exceptions while building the parser or actually parsing and display it nicely. 42 stderr.writefln( ex.msg ); 43 return; 44 } 45 46 bool filterFiles( string name ) 47 { 48 if( !name.exists ) 49 return false; 50 51 if( name.isDir ) 52 return false; 53 54 try 55 { 56 return isRegex ? !!name.matchFirst( pattern ) : name.globMatch( pattern ); 57 } 58 catch( RegexException ex ) 59 { 60 stderr.writefln( "Error in regular expression: %s", ex.msg ); 61 assert( false ); 62 } 63 } 64 65 string normalize( string path ) 66 { 67 return path.asNormalizedPath 68 .array 69 .asAbsolutePath 70 .array 71 .idup; 72 } 73 74 if( !directory.isValidPath ) 75 { 76 stderr.writefln( "'%s' is not a valid path" ); 77 return; 78 } 79 80 try 81 { 82 directory = normalize( directory ); 83 auto entries = directory.dirEntries( SpanMode.breadth ) 84 .filter!( filterFiles ) 85 .map!( normalize ); 86 87 foreach( entry; entries ) 88 writeln( entry ); 89 } 90 catch( AssertError ) { } 91 catch( Throwable th ) 92 { 93 stderr.writefln( "Error while searching for files: %s", th.msg ); 94 } 95 }