<feat> + 目录检索设置

This commit is contained in:
nsnail 2022-12-08 10:49:19 +08:00
parent 8b01483d85
commit f3d250ae87
6 changed files with 113 additions and 99 deletions

View File

@ -2,9 +2,17 @@ namespace Dot;
public class DirOption : OptionBase public class DirOption : OptionBase
{ {
[Option('f', "filter", HelpText = nameof(Str.FileSearchPattern), Default = "*.*", ResourceType = typeof(Str))] [Option('e', "exclude", HelpText = nameof(Str.ExcludePathRegexes), ResourceType = typeof(Str))]
public IEnumerable<string> ExcludeRegexes { get; set; }
[Option('f', "filter", HelpText = nameof(Str.FileSearchPattern), Default = "*", ResourceType = typeof(Str))]
public string Filter { get; set; } public string Filter { get; set; }
[Option('d', "max-depth", HelpText = nameof(Str.MaxRecursionDepth), Default = int.MaxValue
, ResourceType = typeof(Str))]
public int MaxRecursionDepth { get; set; }
[Value(0, HelpText = nameof(Str.FolderPath), Default = ".", ResourceType = typeof(Str))] [Value(0, HelpText = nameof(Str.FolderPath), Default = ".", ResourceType = typeof(Str))]
public string Path { get; set; } public string Path { get; set; }

View File

@ -1,4 +1,5 @@
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Text.RegularExpressions;
using Panel = Spectre.Console.Panel; using Panel = Spectre.Console.Panel;
namespace Dot; namespace Dot;
@ -7,6 +8,7 @@ public abstract class FilesTool<TOption> : ToolBase<TOption> where TOption : Dir
{ {
private int _breakCnt; //跳过文件数 private int _breakCnt; //跳过文件数
private ProgressTask _childTask; //子任务进度 private ProgressTask _childTask; //子任务进度
private int _excludeCnt; //排除文件数
private static readonly object _lock = new(); //线程锁 private static readonly object _lock = new(); //线程锁
private int _readCnt; //读取文件数 private int _readCnt; //读取文件数
private int _totalCnt; //总文件数 private int _totalCnt; //总文件数
@ -19,33 +21,31 @@ public abstract class FilesTool<TOption> : ToolBase<TOption> where TOption : Dir
throw new ArgumentException(nameof(Opt.Path), string.Format(Str.PathNotFound, Opt.Path)); throw new ArgumentException(nameof(Opt.Path), string.Format(Str.PathNotFound, Opt.Path));
} }
private static string[] EnumerateFiles(string path, string searchPattern) private string[] EnumerateFiles(string path, string searchPattern, out int excludeCnt)
{ {
var fileList = Directory var exCnt = 0;
.EnumerateFiles(path, searchPattern if (!Opt.ExcludeRegexes.Any()) //默认排除.git 、 node_modules 目录
Opt.ExcludeRegexes = new[] { @"\.git", "node_modules" };
var excludeRegexes = Opt.ExcludeRegexes.Select(x => new Regex(x));
var fileList = Directory.EnumerateFiles(path, searchPattern
, new EnumerationOptions { , new EnumerationOptions {
RecurseSubdirectories = true RecurseSubdirectories = true
, AttributesToSkip = FileAttributes.ReparsePoint , AttributesToSkip
= FileAttributes.ReparsePoint
, IgnoreInaccessible = true
, MaxRecursionDepth = Opt.MaxRecursionDepth
})
.Where(x => {
if (!excludeRegexes.Any(y => y.IsMatch(x))) return true;
++exCnt;
return false;
}) })
.Where(x => !new[] { ".git", "node_modules" }.Any(
y => x.Contains(y, StringComparison.OrdinalIgnoreCase)))
.ToArray(); .ToArray();
excludeCnt = exCnt;
return fileList; return fileList;
} }
protected static void CopyFile(string source, string dest)
{
try {
File.Copy(source, dest, true);
}
catch (UnauthorizedAccessException) {
File.SetAttributes(dest, new FileInfo(dest).Attributes & ~FileAttributes.ReadOnly);
File.Copy(source, dest, true);
}
}
protected FileStream CreateTempFile(out string file) protected FileStream CreateTempFile(out string file)
{ {
file = Path.Combine(Path.GetTempPath(), $"{System.Guid.NewGuid()}.tmp"); file = Path.Combine(Path.GetTempPath(), $"{System.Guid.NewGuid()}.tmp");
@ -85,10 +85,11 @@ public abstract class FilesTool<TOption> : ToolBase<TOption> where TOption : Dir
_breakCnt += breakCnt; _breakCnt += breakCnt;
if (readCnt > 0) _childTask.Increment(1); if (readCnt > 0) _childTask.Increment(1);
_childTask.Description _childTask.Description
= $"{Str.Read}: [green]{_readCnt}[/]/{_totalCnt}, {Str.Write}: [red]{_writeCnt}[/], {Str.Break}: [gray]{_breakCnt}[/]"; = $"{Str.Read}: [green]{_readCnt}[/]/{_totalCnt}, {Str.Write}: [red]{_writeCnt}[/], {Str.Break}: [gray]{_breakCnt}[/], {Str.Exclude}: [yellow]{_excludeCnt}[/]";
} }
} }
protected void UpdateStats(string key) protected void UpdateStats(string key)
{ {
_writeStats.AddOrUpdate(key, 1, (_, oldValue) => oldValue + 1); _writeStats.AddOrUpdate(key, 1, (_, oldValue) => oldValue + 1);
@ -108,7 +109,7 @@ public abstract class FilesTool<TOption> : ToolBase<TOption> where TOption : Dir
.StartAsync(async ctx => { .StartAsync(async ctx => {
var taskSearchfile = ctx.AddTask(Str.SearchingFile).IsIndeterminate(); var taskSearchfile = ctx.AddTask(Str.SearchingFile).IsIndeterminate();
_childTask = ctx.AddTask("-/-", false); _childTask = ctx.AddTask("-/-", false);
fileList = EnumerateFiles(Opt.Path, Opt.Filter); fileList = EnumerateFiles(Opt.Path, Opt.Filter, out _excludeCnt);
_totalCnt = fileList.Count(); _totalCnt = fileList.Count();
taskSearchfile.IsIndeterminate(false); taskSearchfile.IsIndeterminate(false);
taskSearchfile.Increment(100); taskSearchfile.Increment(100);

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<root> <root>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root" xmlns="">
id="root" xmlns="">
<xsd:element name="root" msdata:IsDataSet="true"></xsd:element> <xsd:element name="root" msdata:IsDataSet="true"></xsd:element>
</xsd:schema> </xsd:schema>
<resheader name="resmimetype"> <resheader name="resmimetype">

View File

@ -143,6 +143,12 @@
<data name="NoFileToBeProcessed" xml:space="preserve"> <data name="NoFileToBeProcessed" xml:space="preserve">
<value>没有需要处理的文件</value> <value>没有需要处理的文件</value>
</data> </data>
<data name="ExcludePathRegexes" xml:space="preserve">
<value>排除路径的正则表达式</value>
</data>
<data name="Exclude" xml:space="preserve">
<value>排除</value>
</data>
<data name="NtpReceiveDone" xml:space="preserve"> <data name="NtpReceiveDone" xml:space="preserve">
<value>成功 {0}/{1} , 本机时钟偏移平均值: {2} ms</value> <value>成功 {0}/{1} , 本机时钟偏移平均值: {2} ms</value>
</data> </data>

View File

@ -33,7 +33,7 @@ public sealed class Main : FilesTool<Option>
} }
if (CloneFileWithoutBom(fsr, ref tmpFile)) { if (CloneFileWithoutBom(fsr, ref tmpFile)) {
if (Opt.WriteMode) CopyFile(tmpFile, file); if (Opt.WriteMode) File.Copy(tmpFile, file, true);
ShowMessage(0, 1, 0); ShowMessage(0, 1, 0);
UpdateStats(Path.GetExtension(file)); UpdateStats(Path.GetExtension(file));
} }

View File

@ -47,7 +47,7 @@ public sealed class Main : FilesTool<Option>
if (hasWrote && !isBin) { if (hasWrote && !isBin) {
if (Opt.WriteMode) CopyFile(tmpFile, file); if (Opt.WriteMode) File.Copy(tmpFile, file, true);
ShowMessage(0, 1, 0); ShowMessage(0, 1, 0);
UpdateStats(Path.GetExtension(file)); UpdateStats(Path.GetExtension(file));
} }