private static void ProcessCommand(GrepResultCollection grepResultCollection, IEnumerable <string> files, ConsoleCommand consoleCommand, RegexOptions optionsFlags)
        {
            bool FixedStringsFlag    = consoleCommand.CommandArgs.ContainsKey(ConsoleFlag.FixedStrings);
            bool DeleteFlag          = consoleCommand.CommandArgs.ContainsKey(ConsoleFlag.Delete);
            bool ReplaceFlag         = consoleCommand.CommandArgs.ContainsKey(ConsoleFlag.Replace);
            bool WriteFlag           = consoleCommand.CommandArgs.ContainsKey(ConsoleFlag.Write);
            bool FileNamesOnlyFlag   = consoleCommand.CommandArgs.ContainsKey(ConsoleFlag.FileNamesOnly);
            bool FileSizeMinimumFlag = consoleCommand.CommandArgs.ContainsKey(ConsoleFlag.FileSizeMinimum);
            bool FileSizeMaximumFlag = consoleCommand.CommandArgs.ContainsKey(ConsoleFlag.FileSizeMaximum);
            bool NResultsFlag        = consoleCommand.CommandArgs.ContainsKey(ConsoleFlag.NResults);

            int FileReadFailedCount    = 0;
            int FileWriteFailedCount   = 0;
            int DeleteSuccessCount     = 0;
            int ReplacedSuccessCount   = 0;
            int TotalFilesMatchedCount = 0;

            long FileSizeMin = GetFileSizeMinimum(consoleCommand);
            long FileSizeMax = GetFileSizeMaximum(consoleCommand);

            // Build content search pattern
            string SearchPattern = BuildSearchPattern(consoleCommand);
            Regex  SearchRegex   = new Regex(SearchPattern, optionsFlags);

            if (FileNamesOnlyFlag)
            {
                Regex FileNameRegex = new Regex(@"^(.+)[\/\\](?<FileName>[^\/\\]+)$");
                var   Matches       = new List <GrepResult>();

                files.ToList().ForEach(file =>
                {
                    if (!NResultsFlag || Matches.Count < Convert.ToInt32(consoleCommand.CommandArgs[ConsoleFlag.NResults]))
                    {
                        // Don't want to waste any time on files that have already been added
                        bool FileAdded = Matches.Any(x => x.SourceFile == file);
                        if (!FileAdded)
                        {
                            // Parse filename from path
                            var FileNameMatch = FileNameRegex.Match(file)?.Groups["FileName"];
                            if (FileNameMatch != null)
                            {
                                // Query against filename
                                var SearchMatch = SearchRegex.Match(FileNameMatch.Value);
                                if (SearchMatch != Match.Empty)
                                {
                                    // Write operations
                                    bool isWriteOperation = ReplaceFlag || DeleteFlag;
                                    if (isWriteOperation)
                                    {
                                        ProcessWriteOperations(consoleCommand, file, SearchPattern, Matches.Count, ref file, ref TotalFilesMatchedCount, ref DeleteSuccessCount, ref ReplacedSuccessCount, ref FileWriteFailedCount);
                                    }
                                    else
                                    {
                                        int TrailingContextStringStartIndex = FileNameMatch.Index + SearchMatch.Index + SearchMatch.Length;

                                        // Validate any filesize parameters
                                        var FileSize = FileSizeMaximumFlag || FileSizeMinimumFlag ? WindowsUtils.GetFileSizeOnDisk(file) : -1;
                                        bool FileSizevalidateSuccess = ValidateFileSize(consoleCommand, FileSize, FileSizeMin, FileSizeMax);

                                        if (FileSizevalidateSuccess)
                                        {
                                            GrepResult GrepResult = new GrepResult(file, ResultScope.FileName)
                                            {
                                                FileSize              = FileSize,
                                                LeadingContextString  = file.Substring(0, FileNameMatch.Index + SearchMatch.Index),
                                                MatchedString         = SearchMatch.Value,
                                                TrailingContextString = file.Substring(TrailingContextStringStartIndex, file.Length - TrailingContextStringStartIndex)
                                            };

                                            Matches.Add(GrepResult);
                                        }
                                    }
                                }
                            }
                        }
                    }
                });

                TotalFilesMatchedCount = Matches.Count();
                grepResultCollection.AddItemRange(Matches);
            }
            else
            {
                if (consoleCommand.CommandArgs[ConsoleFlag.SearchTerm] == string.Empty)
                {
                    throw new Exception("Error: Search term not supplied");
                }

                files.AsParallel().ForAll(file =>
                {
                    try
                    {
                        if (!NResultsFlag || grepResultCollection.Count < Convert.ToInt32(consoleCommand.CommandArgs[ConsoleFlag.NResults]))
                        {
                            List <Match> Matches = new List <Match>();

                            // Validate any filesize parameters
                            var FileSize = FileSizeMaximumFlag || FileSizeMinimumFlag ? WindowsUtils.GetFileSizeOnDisk(file) : -1;
                            bool FileSizevalidateSuccess = ValidateFileSize(consoleCommand, FileSize, FileSizeMin, FileSizeMax);

                            if (FileSizevalidateSuccess)
                            {
                                string FileRaw = File.ReadAllText(file);

                                Matches = SearchRegex.Matches(FileRaw).ToList();
                                if (Matches.Any())
                                {
                                    // Write operations
                                    bool isWriteOperation = ReplaceFlag || DeleteFlag;
                                    if (isWriteOperation)
                                    {
                                        ProcessWriteOperations(consoleCommand, file, SearchPattern, Matches.Count, ref FileRaw, ref TotalFilesMatchedCount, ref DeleteSuccessCount, ref ReplacedSuccessCount, ref FileWriteFailedCount);
                                    }

                                    // Read operations
                                    else
                                    {
                                        BuildSearchResultsFileContent(consoleCommand, grepResultCollection, Matches, file, FileSize, FileRaw);

                                        lock (_SearchLock)
                                        {
                                            TotalFilesMatchedCount++;
                                        }
                                    }
                                }
                            }
                        }
                    }
                    catch
                    {
                        lock (_SearchLock)
                        {
                            FileReadFailedCount++;
                        }
                    }
                });
            }

            // Notify the user of any files that could not be read from or written to
            PublishFileAccessSummary(FileReadFailedCount, FileWriteFailedCount);

            // Publish command summary to console
            PublishCommandSummary(consoleCommand, grepResultCollection, TotalFilesMatchedCount, DeleteSuccessCount, ReplacedSuccessCount);
        }
        private static void ProcessCommand(GrepResultCollection grepResultCollection, IEnumerable <string> files, ConsoleCommand consoleCommand, RegexOptions optionsFlags)
        {
            bool FixedStringsFlag  = consoleCommand.CommandArgs.ContainsKey(ConsoleFlag.FixedStrings);
            bool DeleteFlag        = consoleCommand.CommandArgs.ContainsKey(ConsoleFlag.Delete);
            bool ReplaceFlag       = consoleCommand.CommandArgs.ContainsKey(ConsoleFlag.Replace);
            bool WriteFlag         = consoleCommand.CommandArgs.ContainsKey(ConsoleFlag.Write);
            bool FileNamesOnlyFlag = consoleCommand.CommandArgs.ContainsKey(ConsoleFlag.FileNamesOnly);
            bool IgnoreBreaksFlag  = consoleCommand.CommandArgs.ContainsKey(ConsoleFlag.IgnoreBreaks);

            int FileReadFailedCount  = 0;
            int FileWriteFailedCount = 0;

            int DeleteSuccessCount   = 0;
            int ReplacedSuccessCount = 0;

            int FilesMatchedCount = 0;

            // Build content search pattern
            string SearchPattern = BuildSearchPattern(consoleCommand);
            Regex  SearchRegex   = new Regex(SearchPattern, optionsFlags);

            if (FileNamesOnlyFlag)
            {
                Regex FileNameRegex = new Regex(@"^(.+)[\/\\](?<FileName>[^\/\\]+)$");

                var Matches = new List <GrepResult>();
                files.ToList().ForEach(file =>
                {
                    // Don't want to waste any time on files that have already been added
                    bool FileAdded = Matches.Any(x => x.SourceFile == file);

                    if (!FileAdded)
                    {
                        // Parse filename from path
                        var FileNameMatch = FileNameRegex.Match(file)?.Groups["FileName"];
                        if (FileNameMatch != null)
                        {
                            // Query against filename
                            var SearchMatch = SearchRegex.Match(FileNameMatch.Value);
                            if (SearchMatch != Match.Empty)
                            {
                                var MatchedString = SearchMatch.Groups["MatchedString"];
                                int TrailingContextStringStartIndex = FileNameMatch.Index + FileNameMatch.Value.ToLower().IndexOf(MatchedString.Value.ToLower()) + MatchedString.Length;

                                GrepResult GrepResult = new GrepResult(file, ResultScope.FileName)
                                {
                                    LeadingContextString  = file.Substring(0, FileNameMatch.Index),
                                    MatchedString         = MatchedString.Value,
                                    TrailingContextString = file.Substring(TrailingContextStringStartIndex, file.Length - TrailingContextStringStartIndex)
                                };

                                Matches.Add(GrepResult);
                            }
                        }
                    }
                });

                FilesMatchedCount = Matches.Count();
                grepResultCollection.AddItemRange(Matches);
            }
            else
            {
                files.AsParallel().ForAll(file =>
                {
                    try
                    {
                        List <Match> Matches = new List <Match>();

                        string FileRaw = File.ReadAllText(file);

                        // Apply linebreak filtering options
                        if (IgnoreBreaksFlag)
                        {
                            string FileLineBreakFilteredNull  = FileRaw.Replace("\r", string.Empty).Replace("\n", string.Empty);
                            string FileLineBreakFilteredSpace = Regex.Replace(FileRaw, @"[\r\n]+", " ");

                            Matches.AddRange(SearchRegex.Matches(FileLineBreakFilteredNull));
                            Matches.AddRange(SearchRegex.Matches(FileLineBreakFilteredSpace));
                        }
                        else
                        {
                            Matches = SearchRegex.Matches(FileRaw).ToList();
                        }

                        if (Matches.Any())
                        {
                            // Write operations
                            bool isWriteOperation = ReplaceFlag || DeleteFlag;
                            if (isWriteOperation)
                            {
                                List <ConsoleItem> ConsoleItemCollection = new List <ConsoleItem>();

                                // FileName
                                ConsoleItemCollection.Add(new ConsoleItem()
                                {
                                    ForegroundColor = ConsoleColor.DarkYellow, Value = $"{file} "
                                });

                                try
                                {
                                    if (DeleteFlag)
                                    {
                                        // Delete file
                                        File.Delete(file);

                                        ConsoleItemCollection.Add(new ConsoleItem()
                                        {
                                            ForegroundColor = ConsoleColor.Red, Value = $"Deleted"
                                        });

                                        lock (_searchLock)
                                        {
                                            DeleteSuccessCount++;
                                        }
                                    }
                                    else if (ReplaceFlag)
                                    {
                                        // Replace all occurrences in file
                                        FileRaw = Regex.Replace(FileRaw, SearchPattern, consoleCommand.CommandArgs[ConsoleFlag.Replace]);
                                        File.WriteAllText(file, FileRaw);

                                        string MatchesText = Matches.Count == 1 ? "match" : "matches";
                                        ConsoleItemCollection.Add(new ConsoleItem()
                                        {
                                            ForegroundColor = ConsoleColor.DarkMagenta, Value = $"{Matches.Count} {MatchesText}"
                                        });

                                        lock (_searchLock)
                                        {
                                            ReplacedSuccessCount += Matches.Count;
                                        }
                                    }
                                }
                                catch (Exception ex)
                                {
                                    ConsoleItemCollection.Add(new ConsoleItem()
                                    {
                                        ForegroundColor = ConsoleColor.Gray, BackgroundColor = ConsoleColor.DarkRed, Value = $"Access Denied"
                                    });

                                    lock (_searchLock)
                                    {
                                        FileWriteFailedCount++;
                                    }
                                }
                                finally
                                {
                                    // Empty buffer
                                    ConsoleItemCollection.Add(new ConsoleItem()
                                    {
                                        Value = Environment.NewLine
                                    });

                                    ConsoleUtils.WriteConsoleItemCollection(ConsoleItemCollection);

                                    lock (_searchLock)
                                    {
                                        FilesMatchedCount++;
                                    }
                                }
                            }

                            // Read operations
                            else
                            {
                                BuildSearchResultsFileContent(consoleCommand, grepResultCollection, Matches, file, FileRaw, SearchPattern);

                                lock (_searchLock)
                                {
                                    FilesMatchedCount++;
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        lock (_searchLock)
                        {
                            FileReadFailedCount++;
                        }
                    }
                });
            }

            // Notify the user of any files that could not be read from or written to
            PublishFileAccessSummary(FileReadFailedCount, FileWriteFailedCount);

            // Publish command summary to console
            PublishCommandSummary(consoleCommand, grepResultCollection, FilesMatchedCount, DeleteSuccessCount, ReplacedSuccessCount);
        }