new code2md
Code2md\Code2md.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
Code2md\Code2mdTask.cs
public class Code2mdTask
{
public string CodePath { get; set; }
public string MarkdownTitle { get; set; }
public string DstCodePath { get; set; }
public string DstMdCodePath { get; set; }
}
Code2md\Program.cs
using System.Collections.Concurrent;
using System.Text.RegularExpressions;
using System.Xml;
class Program
{
private static string SourceDirectory = string.Empty;
private static string DirectorySuffix = string.Empty;
private static readonly DateTime Now = DateTime.Now;
// @"D:\inetpub\wwwroot\Mes\szaddon\szpH060\HSLPAD";
// @"D:\inetpub\wwwroot\Mes\szaddon\szpH060\Picture";
// @"D:\inetpub\wwwroot\Mes\szaddon\szpH060\OQC_reports";
private static readonly List<string> ExcludedEqualDirectories = new List<string> { ".github", ".vscode", "bin", "obj" };
private static readonly string DestinationDirectory = @"Z:\inetpub\wwwroot\Mes\szaddon\szpH060\HSLPAD";
private static readonly ConcurrentQueue<Code2mdTask> FileMoveQueue = new ConcurrentQueue<Code2mdTask>();
private static readonly CancellationTokenSource CancellationTokenSource = new CancellationTokenSource();
private static readonly ManualResetEventSlim AllFilesProcessed = new ManualResetEventSlim(false);
private static int _totalFiles = 0;
private static int _completedFiles = 0;
private static readonly object _lockObject = new object();
static void Main(string[] args)
{
if (args.Length == 0)
{
System.Console.WriteLine("请传入文件夹路径");
return;
}
SourceDirectory = args[0];
try
{
// 检查源目录是否存在
if (!Directory.Exists(SourceDirectory))
{
Console.WriteLine($"错误: 源目录 {SourceDirectory} 不存在。");
return;
}
// 扫描源目录并准备移动任务
Console.WriteLine("正在扫描文件...");
System.Console.WriteLine("输入文件夹后缀:");
DirectorySuffix = System.Console.ReadLine() ?? string.Empty;
string[] directories = Directory.GetDirectories(SourceDirectory);
var getFileTasks = new List<Task>();
foreach (string dirPath in directories)
{
bool flowControl = FilterFolder(dirPath);
if (!flowControl)
{
continue;
}
getFileTasks.Add(Task.Run(() => ScanDirectory(dirPath)));
}
getFileTasks.Add(Task.Run(() => ScanDirectory(SourceDirectory)));
Task.WaitAll(getFileTasks);
Console.WriteLine($"已扫描完成,共找到 {_totalFiles} 个文件。");
if (_totalFiles == 0)
{
Console.WriteLine("没有文件需要Code2md转换。");
return;
}
// 启动进度显示线程
var progressThread = new Thread(ShowProgress);
progressThread.IsBackground = true;
progressThread.Start();
// 启动多个工作线程
const int maxThreads = 8;
var tasks = new Task[maxThreads];
for (int i = 0; i < maxThreads; i++)
{
tasks[i] = Task.Run(() => CodeBackup(CancellationTokenSource.Token));
}
// 等待所有任务完成
Task.WaitAll(tasks);
AllFilesProcessed.Wait();
Console.WriteLine("\n所有文件移动完成!");
}
catch (Exception ex)
{
Console.WriteLine($"\n发生致命错误: {ex.Message}");
}
finally
{
CancellationTokenSource.Cancel();
AllFilesProcessed.Dispose();
}
Console.WriteLine("============备份完成============");
}
private static bool FilterFolder(string dirPath)
{
var dirName = Path.GetFileNameWithoutExtension(dirPath);
if (ExcludedEqualDirectories.Exists(d => d.Equals(dirName)))
{
return false;
}
return true;
}
private static void ScanDirectory(string sourcePath)
{
try
{
GetFiles(sourcePath);
string[] directories = Directory.GetDirectories(sourcePath);
foreach (string directory in directories)
{
bool flowControl = FilterFolder(directory);
if (!flowControl)
{
continue;
}
ScanDirectory(directory);
}
}
catch (Exception ex)
{
Console.WriteLine($"扫描目录时出错 ({sourcePath}): {ex.Message}");
}
}
private static void GetFiles(string sourcePath)
{
var regex = new Regex(@"\.(cs|js|html|css|py|java|cpp|h|xaml|ts|csproj|bat|sln|json|go)$", RegexOptions.IgnoreCase);
var files = Directory.EnumerateFiles(sourcePath, "*", SearchOption.TopDirectoryOnly).Where(file => regex.IsMatch(file));
foreach (string filePath in files)
{
string relativePath = Path.GetRelativePath(SourceDirectory, filePath);
string grandFatherFolderPath = Path.GetDirectoryName(SourceDirectory)!;
string brotherFolderPath = Path.GetFileName(SourceDirectory) + $"_{Now:yyyyMMdd_HHmmss}_{DirectorySuffix}";
string dstCodePath = Path.Combine(grandFatherFolderPath, brotherFolderPath, relativePath);
string dstMdCodePath = Path.Combine(SourceDirectory, "zz_pro", brotherFolderPath, relativePath + ".md");
FileMoveQueue.Enqueue(
new Code2mdTask
{
CodePath = filePath,
MarkdownTitle = relativePath,
DstCodePath = dstCodePath,
DstMdCodePath = dstMdCodePath
}
);
Interlocked.Increment(ref _totalFiles);
}
}
private static void CodeBackup(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
if (FileMoveQueue.TryDequeue(out Code2mdTask? task))
{
if (task != null && string.IsNullOrEmpty(task.CodePath))
{
continue; // 跳过空任务
}
System.Console.WriteLine($"正在处理文件: {task.CodePath} -> {task.MarkdownTitle}");
try
{
Code2md(task);
Interlocked.Increment(ref _completedFiles);
}
catch (Exception ex)
{
Console.WriteLine($"复制文件时出错 ({task.CodePath} -> {task.MarkdownTitle}): {ex.Message}");
}
}
else if (_completedFiles == _totalFiles)
{
AllFilesProcessed.Set();
break;
}
else
{
// 队列暂时为空,等待片刻
Thread.Sleep(100);
}
}
}
private static void Code2md(Code2mdTask code2mdTask, int maxRetries = 3)
{
int retries = 0;
while (true)
{
try
{
string codePath = code2mdTask.CodePath;
string markdownTitle = code2mdTask.MarkdownTitle;
string dstCodePath = code2mdTask.DstCodePath;
string dstMdCodePath = code2mdTask.DstMdCodePath;
if (!File.Exists(dstCodePath))
{
if (!Directory.Exists(Path.GetDirectoryName(dstCodePath)))
{
Directory.CreateDirectory(Path.GetDirectoryName(dstCodePath)!);
}
File.Copy(codePath, dstCodePath, false);
}
if (!File.Exists(dstMdCodePath))
{
if (!Directory.Exists(Path.GetDirectoryName(dstMdCodePath)))
{
Directory.CreateDirectory(Path.GetDirectoryName(dstMdCodePath)!);
}
File.Copy(codePath, dstMdCodePath, false);
}
// 验证文件是否成功移动
if (!File.Exists(dstCodePath) || !File.Exists(dstMdCodePath))
{
throw new IOException("文件复制后不存在于目标位置");
}
break;
}
catch (Exception ex)
{
retries++;
if (retries > maxRetries)
{
// Console.WriteLine($"文件移动失败 ({codePath} -> {markdownTitle}): {ex.Message}");
throw;
}
// 等待一段时间后重试
Thread.Sleep(500 * retries);
}
}
}
private static void ShowProgress()
{
while (!AllFilesProcessed.IsSet)
{
lock (_lockObject)
{
Console.CursorLeft = 0;
Console.Write($"进度: {_completedFiles}/{_totalFiles} 文件 ({_completedFiles * 100.0 / Math.Max(1, _totalFiles):F2}%)");
}
Thread.Sleep(100);
}
}
}