using System; using System.Collections.Generic; using System.IO; using System.Linq; namespace RobvanderWoude { internal class Count { static readonly string progver = "1.00"; static int Main( string[] args ) { bool quietmode = false; int count = 0; string filter = string.Empty; SearchOption searchoption = SearchOption.TopDirectoryOnly; if ( args.Contains( "/?" ) ) { return ShowHelp( ); } foreach ( string arg in args ) { if ( arg[0] == '/' ) { if ( arg.ToUpper( ) == "/Q" ) { if ( quietmode ) { return ShowHelp( "Duplicate command line switch /Q" ); } quietmode = true; } else if ( arg.ToUpper( ) == "/S" && !Console.IsInputRedirected ) { if ( searchoption == SearchOption.AllDirectories ) { return ShowHelp( "Duplicate command line switch /S" ); } searchoption = SearchOption.AllDirectories; } else { return ShowHelp( "Invalid command line switch {0}", arg ); } } else { if ( !string.IsNullOrWhiteSpace( filter ) ) { if ( Console.IsInputRedirected ) { return ShowHelp( "Duplicate filter specification" ); } else { return ShowHelp( "Duplicate file specification" ); } } filter = arg; } } if ( Console.IsInputRedirected ) { while ( Console.In.Peek( ) != -1 ) { string line = Console.ReadLine( ); if ( line.Contains( filter ) ) { count++; } } } else { if ( args.Length == 0 ) { return ShowHelp( ); } try { string dir = Directory.GetParent( filter ).FullName; string files = Path.GetFileName( filter ); if ( Directory.Exists( filter ) ) { dir = Path.GetFullPath( filter ); files = "*.*"; } count = Directory.GetFiles( dir, files, searchoption ).Length; } catch( Exception e ) { return ShowHelp( e.Message ); } } if ( !quietmode ) { Console.WriteLine( count ); } return count; } public static int ShowHelp( params string[] errmsg ) { #region Error Message if ( errmsg.Length > 0 ) { List errargs = new List( errmsg ); errargs.RemoveAt( 0 ); Console.Error.WriteLine( ); Console.ForegroundColor = ConsoleColor.Red; Console.Error.Write( "ERROR:\t" ); Console.ForegroundColor = ConsoleColor.White; Console.Error.WriteLine( errmsg[0], errargs.ToArray( ) ); Console.ResetColor( ); } #endregion Error Message #region Help Text /* Count.exe, Version 1.00 Count specified objects and return result as errorlevel Usage: Count.exe filespec [ /S ] [ /Q ] or: some_prog | Count.exe [ filter ] [ /Q ] Where: filespec specifies files to be counted (default: *.*) some_prog program whose output is to be counted (all lines) filter filter for some_prog (count lines containing filter) /Q Quiet mode: no screen output /S recursive (include Subdirectories) Examples: ========= Count number of *.exe files in C:\Windows\System32 and subdirectories: Count.exe C:\Windows\System32\*.exe /S Count number of subdirectories in C:\Windows\System32: DIR /AD /B /S C:\Windows\System32 | Count.exe Count number of environment variables: SET | Count.exe "=" Notes: Instead of Count.exe, one could use Windows' native FIND.EXE with its /C switch in a FOR /F loop, but Count.exe may make your batch code easier to read by using SET Count=%ErrorLevel% Count.exe returns the number of (matching) lines, not the number of occurrences of the specified filter string. Count result is displayed on screen and returned as errorlevel; both are limited to 32-bit integer values. Return code (\"ErrorLevel\") equals count result, or -1 for (command line) errors. Written by Rob van der Woude https://www.robvanderwoude.com */ #endregion Help Text #region Display Help Text Console.Error.WriteLine( ); Console.Error.WriteLine( "Count.exe, Version {0}", progver ); Console.Error.WriteLine( "Count specified objects and return result as errorlevel" ); Console.Error.WriteLine( ); Console.Error.Write( "Usage: " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.WriteLine( "Count.exe filespec [ /S ] [ /Q ]" ); Console.ResetColor( ); Console.Error.WriteLine( ); Console.Error.Write( " or: " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.WriteLine( "some_prog | Count.exe [ filter ] [ /Q ]" ); Console.ResetColor( ); Console.Error.WriteLine( ); Console.Error.Write( "Where: " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( "filespec" ); Console.ResetColor( ); Console.Error.WriteLine( " specifies files to be counted (default: *.*)" ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( " some_prog" ); Console.ResetColor( ); Console.Error.WriteLine( " program whose output is to be counted (all lines)" ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( " filter" ); Console.ResetColor( ); Console.Error.WriteLine( " filter for some_prog (count lines containing filter)" ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( " /Q Q" ); Console.ResetColor( ); Console.Error.WriteLine( "uiet mode: no screen output" ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( " /S" ); Console.ResetColor( ); Console.Error.Write( " recursive (include " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( "S" ); Console.ResetColor( ); Console.Error.WriteLine( "ubdirectories)" ); Console.Error.WriteLine( ); Console.Error.WriteLine( "Examples:" ); Console.Error.WriteLine( "=========" ); Console.Error.WriteLine( ); Console.Error.WriteLine( "Count number of *.exe files in C:\\Windows\\System32 and subdirectories:" ); Console.ForegroundColor = ConsoleColor.Green; Console.Error.WriteLine( "Count.exe C:\\Windows\\System32\\*.exe /S" ); Console.ResetColor( ); Console.Error.WriteLine( ); Console.Error.WriteLine( "Count number of subdirectories in C:\\Windows\\System32:" ); Console.ForegroundColor = ConsoleColor.Green; Console.Error.WriteLine( "DIR /AD /B /S C:\\Windows\\System32 | Count.exe" ); Console.ResetColor( ); Console.Error.WriteLine( ); Console.Error.WriteLine( "Count number of environment variables:" ); Console.ForegroundColor = ConsoleColor.Green; Console.Error.WriteLine( "SET | Count.exe \"=\"" ); Console.ResetColor( ); Console.Error.WriteLine( ); Console.Error.WriteLine( "Notes: Instead of Count.exe, one could use Windows' native FIND.EXE" ); Console.Error.WriteLine( " with its /C switch in a FOR /F loop, but Count.exe may make" ); Console.Error.Write( " your batch code easier to read, by using " ); Console.ForegroundColor = ConsoleColor.Green; Console.Error.WriteLine( "SET Count=%ErrorLevel%" ); Console.ResetColor( ); Console.Error.WriteLine( " Count.exe returns the number of (matching) lines, not the" ); Console.Error.WriteLine( " number of occurrences of the specified filter string." ); Console.Error.WriteLine( " Count result is displayed on screen and returned as errorlevel;" ); Console.Error.WriteLine( " both are limited to 32-bit integer values." ); Console.Error.WriteLine( " Return code (\"ErrorLevel\") equals count result, or -1 for" ); Console.Error.WriteLine( " (command line) errors." ); Console.Error.WriteLine( ); Console.Error.WriteLine( "Written by Rob van der Woude" ); Console.Error.WriteLine( "https://www.robvanderwoude.com" ); #endregion Display Help Text return -1; } } }