为何find命令已设置忽略.git目录仍扫描该目录并报错?
为什么find命令仍会扫描.git目录?
这个问题我之前碰到过,核心原因是你用的-not -path只是在find找到文件/目录后过滤掉输出,但它依然会先遍历整个.git目录下的所有内容——这就是为什么你还是会看到.git相关的错误,因为find在遍历过程中尝试访问这些路径了,只是最后没把它们加入结果而已。
哪怕你追加了-not -path '**/.git/objects/**'也没用,因为find还是会先进入.git目录,再去遍历objects下的内容,遍历过程中遇到不存在的路径(比如Git仓库里的松散对象被清理、或是临时生成后又被删除的文件),就会抛出「No such file or directory」的错误。
正确的解决方案:用-prune跳过整个目录
要彻底避免find扫描.git和node_modules目录,你需要用-prune参数,它能让find直接跳过指定目录的遍历,根本不会进入其中。推荐的命令写法如下:
find . \( -path '**/.git' -o -path '**/node_modules' \) -prune -o -type f -exec sed -i '' s/typescript-library-skeleton/xxx/g {} +
命令拆分解释:
\( -path '**/.git' -o -path '**/node_modules' \) -prune:匹配到.git或node_modules目录时,用-prune终止对该目录的遍历,完全不会进入其中查找内容。-o:逻辑「或」,表示当前面的条件(匹配到要跳过的目录)不满足时,执行后面的操作。-type f -exec sed ... {} +:对剩下的所有普通文件执行sed替换操作,用-exec ... {} +比xargs更安全,能完美处理文件名含空格、特殊字符的场景。
如果你更习惯用xargs,也可以调整成下面的写法(同样避免特殊文件名问题):
find . \( -path '**/.git' -o -path '**/node_modules' \) -prune -o -type f -print0 | xargs -0 sed -i '' s/typescript-library-skeleton/xxx/g
额外说明
之前的命令报错,本质是因为-not -path没有阻止find遍历目录,只是在最后过滤结果。而Git仓库的.git/objects目录里的内容可能会被Git的后台操作(比如git gc)动态清理或修改,导致find遍历到这些路径时,文件/目录已经不存在,从而触发错误。用-prune就能从根源上避免这个问题。
内容的提问来源于stack exchange,提问作者user5047085
相关产品推荐
相关产品推荐

