题目重点:把目录遍历与谓词组合分开,明确是否跟随链接,用对象身份处理环并保留路径别名输出政策。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 训练版搜索普通文件,可组合size≥threshold与指定suffix;是否大小写敏感、扩展名是否含点为接口参数。
- 默认不跟随symlink;启用跟随时必须固定边界、失败和输出政策。本文区分按路径输出与按文件对象去重。
- 真实文件系统采用filesystem/device id+inode等稳定对象身份;模拟题可由API提供object_id,不假定字符串路径唯一标识对象。
解题路线
- FileEntry只负责metadata与children接口,Predicate负责matches;SizePredicate、SuffixPredicate可通过And/Or组合。Traversal只枚举与处理错误,Search收集或yield匹配项,避免每新增条件改遍历。
- 用显式DFS栈避免深目录递归溢出。读取子目录可能失败、文件可能消失,按合同返回部分结果与错误或严格失败,不能悄悄吞异常。大目录流式yield控制结果内存。
- 跟随symlink会形成有向图:a/link→b,b/link→a。用对象身份的active ancestry集合检测当前路径环;全局visited可以避免重复遍历共享子树,但也会减少不同路径别名结果,两者语义不同。
- 若目标只要唯一物理文件,用全局对象visited去重;若按路径列出别名,使用当前祖先防环并允许同对象不同路径,但需深度/节点预算限制膨胀。明确hard link是否输出多路径。
- 路径字符串有相对/绝对、..、链接别名和改名,两个不同文本可达同对象;只做string visited不能阻断所有对象环。canonicalize可帮助但有额外I/O与并发变化,不能当原子快照。
- 如果是真实权限边界的搜索,解析后仍核对允许root、不要仅用文本前缀判断;为稳定结果可选择快照或接受弱一致并标注变更。讨论TOCTOU时结合实际API,不假称所有文件平台都提供相同能力。
手动走一遍
训练图root/a/link指向root/b,root/b/back指向root/a。DFS到a→b→a时发现a已在祖先链,停止这条边。若root又有另一路径alias_b,按路径模式可以输出其文件别名,按物理文件模式则全局visited略过,返回合同必须先说清。
规模与取舍
唯一对象模式O(V+E+谓词成本),栈和visited O(V)。别名路径模式可能枚举指数多条简单路径,祖先防环保证终止但不保证线性。流式输出省结果存储,不能省已访问身份记录。
易错点与追问
容易失分的边界
- 路径string等同对象身份。
- 全局visited与当前路径active混用,误删合法别名。
- 把suffix过滤放在目录层,漏掉目录下文件。
- 不定义权限错误/消失文件政策。
- 仅DFS就承诺有链接图始终O(N)。
继续深挖
- 要求返回所有路径别名时如何限制搜索爆炸?
- 同对象内容/大小在搜索中改变,结果合同是什么?
- 远程文件API调用昂贵,怎样批量metadata与缓存?
- 过滤条件支持not或动态插件,如何保持测试边界?
