1 Commits

4 changed files with 289 additions and 1 deletions

14
.vscode/launch.json vendored
View File

@ -11,6 +11,20 @@
"preLaunchTask": "Build", "preLaunchTask": "Build",
"program": "${workspaceFolder}/bin/Debug/net8.0/win-x64/File-Folder-Helper.dll", "program": "${workspaceFolder}/bin/Debug/net8.0/win-x64/File-Folder-Helper.dll",
"args": [ "args": [
"s",
"X",
"X:/Production/Logs/EAF-Warn-Error-002-014-004~X:/Production/Logs/EAF-Info-Warn-002-059-000~X:/Production/Logs/EAF-Info-Warn-002-060-000~X:/Production/Logs/EAF-Info-Warn-002-061-001",
"Day-Helper-2025-09-26",
"EAF_INFO*.lo*~EAF_WARN*.lo*",
"S1F4 W-Bit",
"yyyy-MM-dd HH:mm:ss,fff",
"0",
"10",
"EAF_INFO*.lo*~EAF_WARN*.lo*",
"DF_Error*.lo*~DF_Notification*.lo*~DF_Unit*.lo*",
"2025-*.log",
"X:/Production/Logs/EAF-Warn-Error-002-014-004~X:/Production/Logs/EAF-Info-Warn-002-059-000~X:/Production/Logs/EAF-Info-Warn-002-060-000~X:/Production/Logs/EAF-Info-Warn-002-061-001",
"X:/Production/Logs/EDA_004_016_001~X:/Production/Logs/EDA_004_021_000",
"s", "s",
"X", "X",
"A:/6-Other-Large-Z/Linux-Ubuntu-Affirm/etc/nginx/include~B:/6-Other-Large-Z/Linux-Ubuntu-BCHS/etc/nginx/include~J:/6-Other-Large-Z/Linux-Ubuntu-JMLC/etc/nginx/include~P:/6-Other-Large-Z/Linux-Ubuntu-Phares/etc/nginx/include", "A:/6-Other-Large-Z/Linux-Ubuntu-Affirm/etc/nginx/include~B:/6-Other-Large-Z/Linux-Ubuntu-BCHS/etc/nginx/include~J:/6-Other-Large-Z/Linux-Ubuntu-JMLC/etc/nginx/include~P:/6-Other-Large-Z/Linux-Ubuntu-Phares/etc/nginx/include",

View File

@ -0,0 +1,272 @@
using Microsoft.Extensions.Logging;
using System.Globalization;
namespace File_Folder_Helper.ADO2025.PI7;
internal static partial class Helper20250926 {
internal static void RenameThenFindFirstAndLast(ILogger<Worker> logger, List<string> args) {
logger.LogInformation(args[0]);
logger.LogInformation(args[1]);
logger.LogInformation(args[2]);
logger.LogInformation(args[3]);
logger.LogInformation(args[4]);
logger.LogInformation(args[5]);
const char star = '*';
const char underscore = '_';
string dateFormat = args[4];
string searchString = args[3];
int seconds = int.Parse(args[5]);
string[] searchPatterns = args[2].Split('~');
string key = searchString.ToLower().Split(' ')[0];
string[] sourceDirectories = Path.GetFullPath(args[0]).Split('~');
if (args.Count == 999) {
Redo(logger, star, underscore, dateFormat, searchString, key, searchPatterns, sourceDirectories);
}
Rename(logger, star, underscore, dateFormat, searchString, key, searchPatterns, sourceDirectories);
if (seconds > 0) {
FindFirstAndLast(logger, star, underscore, dateFormat, searchString, seconds, searchPatterns, sourceDirectories);
}
}
private static void Redo(ILogger<Worker> logger, char star, char underscore, string dateFormat, string searchString, string key, string[] searchPatterns, string[] sourceDirectories) {
bool found;
string check;
string[] files;
string[] lines;
string fileName;
string checkFile;
string checkPath;
DateTime lastDate;
DateTime firstDate;
string directoryName;
string[] directories;
string? directoryPath;
foreach (string sourceDirectory in sourceDirectories) {
directories = Directory.GetDirectories(sourceDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string searchPattern in searchPatterns) {
if (searchPattern.Contains(underscore) || !searchPattern.Contains(star)) {
throw new Exception($"{nameof(searchPattern)} must not contain {underscore} and must contain {star}");
}
foreach (string directory in directories) {
directoryName = Path.GetFileName(directory);
files = Directory.GetFiles(directory, searchPattern, SearchOption.AllDirectories);
logger.LogInformation("With search pattern '{SearchPattern}' found {files} file(s)", searchPattern, files.Length);
foreach (string file in files) {
found = false;
lastDate = DateTime.MinValue;
firstDate = DateTime.MinValue;
fileName = Path.GetFileName(file);
directoryPath = Path.GetDirectoryName(file);
if (string.IsNullOrEmpty(directoryPath)) {
logger.LogInformation("skipped (empty) '{directoryPath}'", directoryPath);
continue;
}
try {
lines = File.ReadAllLines(file);
foreach (string line in lines) {
if (!found && line.Contains(searchString)) {
found = true;
}
if (line.Length < dateFormat.Length) {
continue;
}
check = line[..dateFormat.Length];
if (!DateTime.TryParseExact(check, dateFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime logDate)) {
continue;
}
if (firstDate == DateTime.MinValue) {
firstDate = logDate;
}
lastDate = logDate;
}
if (!found) {
checkFile = $"{directoryName}_{firstDate:yyyy-MM-dd_HH-mm-ss}---{lastDate:yyyy-MM-dd_HH-mm-ss}.log";
} else {
checkFile = $"{directoryName}_{firstDate:yyyy-MM-dd_HH-mm-ss}---{lastDate:yyyy-MM-dd_HH-mm-ss}~~~{key}.log";
}
checkPath = Path.Combine(directoryPath, checkFile);
if (checkFile == fileName) {
logger.LogDebug("skipped (match) '{checkFile}'", checkFile);
} else if (File.Exists(checkPath)) {
logger.LogInformation("skipped (exists) '{checkPath}'", checkPath);
} else {
logger.LogInformation("rename to '{checkPath}'", checkPath);
File.Move(file, checkPath);
}
} catch {
logger.LogWarning("skipped (error) {TotalHours} hour(s) -> '{FileInfo}'", file, (DateTime.Now - new FileInfo(file).LastWriteTime).TotalHours);
}
}
}
}
}
}
private static void Rename(ILogger<Worker> logger, char star, char underscore, string dateFormat, string searchString, string key, string[] searchPatterns, string[] sourceDirectories) {
bool found;
string check;
string[] files;
string[] lines;
string checkFile;
string checkPath;
DateTime lastDate;
string[] segments;
DateTime firstDate;
string[] segmentsB;
string directoryName;
string[] directories;
string destinationDirectory;
FileInfo[] fileInfoCollection;
foreach (string sourceDirectory in sourceDirectories) {
directories = Directory.GetDirectories(sourceDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string searchPattern in searchPatterns) {
if (!searchPattern.Contains(underscore) || !searchPattern.Contains(star)) {
throw new Exception($"{nameof(searchPattern)} must contain {underscore} and {star}");
}
segments = searchPattern.Split(star);
segmentsB = segments[0].Split(underscore);
foreach (string directory in directories) {
directoryName = Path.GetFileName(directory);
destinationDirectory = Path.Combine(directory, segmentsB[0], segmentsB[1]);
if (!Directory.Exists(destinationDirectory)) {
_ = Directory.CreateDirectory(destinationDirectory);
}
files = Directory.GetFiles(directory, searchPattern, SearchOption.TopDirectoryOnly);
logger.LogInformation("With search pattern '{SearchPattern}' found {files} file(s)", searchPattern, files.Length);
fileInfoCollection = files.Select(f => new FileInfo(f)).ToArray();
foreach (FileInfo fileInfo in fileInfoCollection.OrderBy(f => f.LastWriteTime)) {
if (fileInfo.Length == 0) {
logger.LogDebug("skipped (0k) '{FileInfo}'", fileInfo.FullName);
continue;
} else if (fileInfo.LastWriteTime > DateTime.Now.AddMinutes(-1)) {
logger.LogDebug("skipped (too new) '{FileInfo}'", fileInfo.FullName);
continue;
}
found = false;
lastDate = DateTime.MinValue;
firstDate = DateTime.MinValue;
try {
lines = File.ReadAllLines(fileInfo.FullName);
foreach (string line in lines) {
if (!found && line.Contains(searchString)) {
found = true;
}
if (line.Length < dateFormat.Length) {
continue;
}
check = line[..dateFormat.Length];
if (!DateTime.TryParseExact(check, dateFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime logDate)) {
continue;
}
if (firstDate == DateTime.MinValue) {
firstDate = logDate;
}
lastDate = logDate;
}
if (!found) {
checkFile = $"{directoryName}_{firstDate:yyyy-MM-dd_HH-mm-ss}---{lastDate:yyyy-MM-dd_HH-mm-ss}.log";
} else {
checkFile = $"{directoryName}_{firstDate:yyyy-MM-dd_HH-mm-ss}---{lastDate:yyyy-MM-dd_HH-mm-ss}~~~{key}.log";
}
checkPath = Path.Combine(destinationDirectory, checkFile);
if (checkFile == fileInfo.Name) {
logger.LogDebug("skipped (match) '{checkFile}'", checkFile);
} else if (File.Exists(checkPath)) {
logger.LogInformation("skipped (exists) '{checkPath}'", checkPath);
} else {
logger.LogInformation("rename to '{checkPath}'", checkPath);
File.Move(fileInfo.FullName, checkPath);
}
} catch {
logger.LogWarning("skipped (error) {TotalHours} hour(s) -> '{FileInfo}'", (DateTime.Now - fileInfo.LastWriteTime).TotalHours, fileInfo.FullName);
}
}
Helpers.HelperDeleteEmptyDirectories.DeleteEmptyDirectories(logger, directory);
}
}
}
}
private static void FindFirstAndLast(ILogger<Worker> logger, char star, char underscore, string dateFormat, string searchString, int seconds, string[] searchPatterns, string[] sourceDirectories) {
string line;
string check;
string[] files;
string[] lines;
DateTime lastDate;
double totalHours;
string[] segments;
TimeSpan timeSpan;
DateTime firstDate;
string[] segmentsB;
string directoryName;
string[] directories;
string searchPatternB;
string destinationDirectory;
FileInfo[] fileInfoCollection;
DateTime logDate = DateTime.MinValue;
foreach (string sourceDirectory in sourceDirectories) {
directories = Directory.GetDirectories(sourceDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string searchPattern in searchPatterns) {
if (!searchPattern.Contains(underscore) || !searchPattern.Contains(star)) {
throw new Exception($"{nameof(searchPattern)} must contain {underscore} and {star}");
}
segments = searchPattern.TrimEnd(star).Split(star);
segmentsB = segments[0].Split(underscore);
foreach (string directory in directories) {
directoryName = Path.GetFileName(directory);
destinationDirectory = Path.Combine(directory, segmentsB[0], segmentsB[1]);
if (!Directory.Exists(destinationDirectory)) {
logger.LogInformation("skipped (doesn't exist) '{destinationDirectory}'", destinationDirectory);
continue;
}
searchPatternB = $"*{segments[^1]}*";
files = Directory.GetFiles(destinationDirectory, searchPatternB, SearchOption.TopDirectoryOnly);
logger.LogInformation("For {destinationDirectory} with search pattern '{SearchPatternB}' found {files} file(s)", destinationDirectory, searchPatternB, files.Length);
fileInfoCollection = files.Select(f => new FileInfo(f)).ToArray();
foreach (FileInfo fileInfo in fileInfoCollection.OrderBy(f => f.LastWriteTime)) {
if (fileInfo.Length == 0) {
logger.LogDebug("skipped (0k) '{FileInfo}'", fileInfo.FullName);
continue;
} else if (fileInfo.LastWriteTime > DateTime.Now.AddMinutes(-1)) {
logger.LogDebug("skipped (too new) '{FileInfo}'", fileInfo.FullName);
continue;
}
lastDate = DateTime.MinValue;
firstDate = DateTime.MinValue;
try {
lines = File.ReadAllLines(fileInfo.FullName);
for (int i = 0; i < lines.Length; i++) {
line = lines[i];
if (!line.Contains(searchString) || lines[i - 1].Length < dateFormat.Length) {
continue;
}
check = lines[i - 1][..dateFormat.Length];
if (!DateTime.TryParseExact(check, dateFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out logDate)) {
continue;
}
timeSpan = logDate - lastDate;
if (firstDate == DateTime.MinValue || timeSpan.TotalSeconds > seconds) {
if (firstDate != DateTime.MinValue) {
totalHours = Math.Round((lastDate - firstDate).TotalHours, 2);
logger.LogInformation("Ran for {totalHours} hour(s) {logDate} - {firstDate} {file}", totalHours, logDate.ToString("HH:mm:ss"), firstDate.ToString("HH:mm:ss"), fileInfo.FullName[directory.Length..]);
}
firstDate = logDate;
}
lastDate = logDate;
}
if (firstDate != DateTime.MinValue && logDate != DateTime.MinValue) {
totalHours = Math.Round((lastDate - firstDate).TotalHours, 2);
logger.LogInformation("Ran for {totalHours} hour(s) {logDate} - {firstDate} {file}", totalHours, logDate.ToString("HH:mm:ss"), firstDate.ToString("HH:mm:ss"), fileInfo.FullName[directory.Length..]);
}
} catch {
logger.LogWarning("skipped (error) {TotalHours} hour(s) -> '{FileInfo}'", (DateTime.Now - fileInfo.LastWriteTime).TotalHours, fileInfo.FullName);
}
}
Helpers.HelperDeleteEmptyDirectories.DeleteEmptyDirectories(logger, directory);
}
}
}
}
}

View File

@ -187,6 +187,8 @@ internal static class HelperDay
ADO2025.PI6.Helper20250726.CopyToCombinedEnumAndIndexFormat(logger, args); ADO2025.PI6.Helper20250726.CopyToCombinedEnumAndIndexFormat(logger, args);
else if (args[1] == "Day-Helper-2025-09-08") else if (args[1] == "Day-Helper-2025-09-08")
ADO2025.PI7.Helper20250908.DebugProxyPass(logger, args); ADO2025.PI7.Helper20250908.DebugProxyPass(logger, args);
else if (args[1] == "Day-Helper-2025-09-26")
ADO2025.PI7.Helper20250926.RenameThenFindFirstAndLast(logger, args);
else else
throw new Exception(appSettings.Company); throw new Exception(appSettings.Company);
} }

View File

@ -18,7 +18,7 @@
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.1" /> <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.1" />
<PackageReference Include="Phares.Metadata" Version="8.0.118.14905" /> <PackageReference Include="Phares.Metadata" Version="8.0.118.14905" />
<PackageReference Include="Phares.Shared" Version="8.0.118.14905" /> <PackageReference Include="Phares.Shared" Version="8.0.118.14905" />
<PackageReference Include="runtime.win-x64.Microsoft.DotNet.ILCompiler" Version="8.0.19" /> <PackageReference Include="runtime.win-x64.Microsoft.DotNet.ILCompiler" Version="8.0.20" />
<PackageReference Include="System.Text.Json" Version="9.0.7" /> <PackageReference Include="System.Text.Json" Version="9.0.7" />
<PackageReference Include="TextCopy" Version="6.2.1" /> <PackageReference Include="TextCopy" Version="6.2.1" />
<PackageReference Include="WindowsShortcutFactory" Version="1.2.0" /> <PackageReference Include="WindowsShortcutFactory" Version="1.2.0" />