commit a86b7f2e8a80ca83f16c279ec91d578019616ea8 Author: Tomato <3199036352@qq.com> Date: Fri Jan 9 13:25:44 2026 +0800 first commit diff --git a/file_matcher/file_matcher.v b/file_matcher/file_matcher.v new file mode 100644 index 0000000..c6fd60a --- /dev/null +++ b/file_matcher/file_matcher.v @@ -0,0 +1,63 @@ +// file_matcher.v +module file_matcher + +// 匹配模式枚举 +pub enum MatchMode { + exact // 精确匹配 + wildcard // 通配符匹配 (* 和 _) + like // 模糊匹配,忽略大小写 +} + +// 通配符匹配函数 +fn wildcard_match(pattern string, name string) bool { + mut i := 0 + mut j := 0 + mut star_idx := -1 + mut match_idx := -1 + + for i < name.len { + if j < pattern.len && (pattern[j] == name[i] || pattern[j] == `_`) { + i++ + j++ + } else if j < pattern.len && pattern[j] == `*` { + star_idx = j + match_idx = i + j++ + } else if star_idx != -1 { + j = star_idx + 1 + match_idx++ + i = match_idx + } else { + return false + } + } + + // 处理模式末尾的 * + for j < pattern.len && pattern[j] == `*` { + j++ + } + + return j == pattern.len +} + +// 主匹配函数 +pub fn match_file(pattern string, filename string, mode MatchMode) bool { + match mode { + .exact { + return filename == pattern + } + .wildcard { + return wildcard_match(pattern, filename) + } + .like { + // 移除%符号,进行模糊匹配 + clean_pattern := pattern.replace('%', '') + return filename.to_lower().contains(clean_pattern.to_lower()) + } + } +} + +// 检查是否为通配符模式 +pub fn is_wildcard_pattern(pattern string) bool { + return pattern.contains('*') || pattern.contains('_') +} \ No newline at end of file diff --git a/main.v b/main.v new file mode 100644 index 0000000..8145065 --- /dev/null +++ b/main.v @@ -0,0 +1,176 @@ +// main.v +module main + +import os +import time +import file_matcher + +fn main() { + // 直接读取目录 + mut current_dir := '.' + print('请输入要搜索的目录 (默认为当前目录): ') + mut input := os.get_line() + if input.trim_space() != '' { + current_dir = input + } + + // 读取搜索模式 + mut search_pattern := '*' + print('请输入搜索模式 (* 显示所有文件): ') + input = os.get_line() + if input.trim_space() != '' { + search_pattern = input + } + + // 验证目录 + if !os.is_dir(current_dir) { + println('错误: 目录 "$current_dir" 不存在!') + return + } + + println('') + println('搜索目录: $current_dir') + println('搜索模式: $search_pattern') + println('开始搜索...') + println('') + + mut scanner := new_scanner(12) + scanner.do_scan_with_search(current_dir, search_pattern) +} + +// 原始Scanner结构体 +struct Scanner { +mut: + max_worker int = 32 + worker_count int + search_request chan string + work_done chan bool + + // 搜索相关字段 + search_pattern string + search_mode file_matcher.MatchMode + match_count int + search_active bool +} + +fn new_scanner(max_worker_count int) &Scanner { + return &Scanner{ + max_worker: max_worker_count + search_request: chan string{cap: 100} + work_done: chan bool{cap: 100} + } +} + +// 设置搜索条件 +fn (mut s Scanner) set_search(pattern string, mode file_matcher.MatchMode) { + s.search_pattern = pattern + s.search_mode = mode + s.search_active = pattern != '' && pattern != '*' + s.match_count = 0 + println('设置搜索: 模式=$pattern, 类型=$mode, 激活=$s.search_active') +} + +// 增强的扫描函数,支持文件过滤 +fn (mut s Scanner) scanner_with_filter(path string, is_master bool) { + items := os.ls(path) or { + // 只在路径不是系统目录时显示错误 + if !path.contains('System Volume Information') && + !path.contains('\$RECYCLE.BIN') && + !path.contains('Windows') { + println('注意: 无法访问目录 "$path"') + } + if is_master { + s.work_done <- true + } + return + } + + for item in items { + full_path := os.join_path(path, item) + + if os.is_dir(full_path) { + if s.worker_count < s.max_worker { + s.search_request <- full_path + } else { + s.scanner_with_filter(full_path, false) + } + } else { + // 如果没有激活搜索,或者文件匹配模式,则输出 + if !s.search_active { + println('$full_path') + s.match_count++ + } else { + if file_matcher.match_file(s.search_pattern, item, s.search_mode) { + println('$full_path') + s.match_count++ + } + } + } + } + + if is_master { + s.work_done <- true + } +} + +// 执行扫描(可选择是否搜索) +fn (mut s Scanner) do_scan_with_search(path string, search_pattern string) { + start := time.now() + + // 设置搜索条件(如果提供了搜索模式) + if search_pattern != '' { + // 自动检测搜索模式 + mut mode := file_matcher.MatchMode.exact + + if search_pattern == '*' { + // 显示所有文件,不激活搜索 + mode = .exact + s.search_active = false + s.search_pattern = '' + } else if file_matcher.is_wildcard_pattern(search_pattern) { + mode = .wildcard + } else if search_pattern.contains('%') { + mode = .like + } + + s.set_search(search_pattern, mode) + println('搜索模式: $search_pattern (${mode})') + } else { + s.search_active = false + s.search_pattern = '' + } + + s.worker_count = 1 + s.match_count = 0 + go s.scanner_with_filter(path, true) + s.watting_for_workers() + + end := time.now() + duration := end - start + + println('') + if s.search_active { + println('找到 ${s.match_count} 个匹配文件') + } else { + println('找到 ${s.match_count} 个文件') + } + println('耗时: ${duration.seconds()} 秒') +} + +// 等待工作线程完成 +fn (mut s Scanner) watting_for_workers() { + for { + select { + path := <- s.search_request { + s.worker_count++ + go s.scanner_with_filter(path, true) + } + _ := <- s.work_done { + s.worker_count-- + if s.worker_count == 0 { + return + } + } + } + } +} \ No newline at end of file diff --git a/main.v.bk b/main.v.bk new file mode 100644 index 0000000..fc9b93e --- /dev/null +++ b/main.v.bk @@ -0,0 +1,82 @@ + +module main +import os +import time + +fn main() { + current_dir := 'C:\\' + mut scanner :=new_scanner(12) + scanner.do_scan(current_dir) +} + + +fn new_scanner(max_worker_count int) &Scanner{ + return &Scanner{ + max_worker: max_worker_count + } +} + + +struct Scanner{ +mut: + max_worker int = 32 + worker_count int + search_request chan string + work_done chan bool +} + + +fn (mut s Scanner)scanner(path string,is_master bool){ + items := os.ls(path) or { + println('列出目录失败: $err\n$path') + s.work_done <- true + return + } + + for item in items { + full_path := os.join_path(path, item) + if os.is_dir(full_path) { + if s.worker_count < s.max_worker{ + s.search_request <- full_path + }else{ + s.scanner(full_path,false) + } + } else { + println('$full_path') + } + } + if is_master{ + s.work_done <- true + } +} + + +fn (mut s Scanner)do_scan(path string){ + start := time.now() + + s.worker_count = 1 + go s.scanner(path,true) + s.watting_for_workers() + + end := time.now() + duration := end - start + println('耗时: ${duration.seconds()} 秒') +} + + +fn (mut s Scanner)watting_for_workers(){ + for { + select { + path := <- s.search_request { + s.worker_count++ + go s.scanner(path,true) + } + _ :=<- s.work_done{ + s.worker_count-- + if s.worker_count == 0{ + return + } + } + } + } +} diff --git a/scanner.exe b/scanner.exe new file mode 100644 index 0000000..1202b65 Binary files /dev/null and b/scanner.exe differ