查找:排除任意级别存在的 n 个不同目录和 m 个不同文件,但包含某些排除目录中的少量文件

查找:排除任意级别存在的 n 个不同目录和 m 个不同文件,但包含某些排除目录中的少量文件

我想递归地查找路径内的所有目录和文件,但想排除一些与给定模式匹配的其他目录和文件。然后我想对搜索结果执行进一步的命令,可能是cpmvrsyncrm结果find

假设我想要修剪整个node_modules,.gitbuild目录以及修剪enhancers目录,但希望在搜索结果中包含一个具有 -name 的文件xyz.js,该文件存在于enhancers目录内未知的深度。

使用下面的命令,我能够实现所需的结果,除了xyz.js搜索结果中包含文件之外。命令很长。

find . -path "./node_modules" -prune -o -path "./.git*" -prune -o -path "./build" -prune -o -path "*/enhancers" -prune -o -print | grep 'xyz.js'

--root
  |--node_modules
  |--public
  |--build
  |--.git
  |--.gitignore
  |--.env
  |--package.json
  |--src
    |--history
    |--store
      |--middleware
        |..
        |..
          |--enhancers
            |..
              |--xyz.js

在上面的示意性目录结构中,|..代表目录内部的未知深度(级别)。

在显示的目录结构中,我想包含搜索结果中的所有文件,除了,

  • 整个node_modules目录
  • 整个.git目录
  • .gitignore文件
  • 整个enhancers目录,但xyz.js在搜索结果中包含文件

有没有更短的方法来做到这一点?主要的混淆在于正则表达式和全局模式之间。

如果我./.git*用替换./\.git*,那么它也有效。

*如果我在 中使用多个*/enhancers,那么它也有效。

find命令中适用哪些搜索文件和目录的模式规则?

答案1

如果您希望能够找到其中的任何文件enhancers,那么您就做不到pruneprune意味着find根本不下降,所以它不可能在那里找到文件。在这里,您不想修剪这些文件,而是排除它们下面的任何文件(除了这些xyz.js文件)。

所以:

find . \( \
          -path ./node_modules -o \
          -path './.git*' -o \
          -path ./build \
       \) -prune -o \( \
          ! -path '*/enhancers' ! -path '*/enhancers/*' -o \
          -name xyz.js \
       \) -print

为了便于阅读,这里有几行。

如果您想对这些文件执行某些操作,请替换-print为。-exec sh -c 'for file do something with "$file"; done' sh {} +

或者,如果您想对输出进行后处理,请使用//-print0选项-z(假设--nullGNU实现或兼容) ,以便它们处理 NUL 分隔的输入。-0grepxargscutsort

答案2

rsync您可以使用两个带有过滤规则的命令行来制作 bash shell 脚本,

#!/bin/bash

rsync -Havn \
 --filter="- target" \
 --filter="- node_modules" \
 --filter="- .git" \
 --filter="- build" \
 --filter="- enhancers" \
 ./ target

rsync -Havn  \
 --filter="+ xyz.js" \
 --filter="+ */" \
 --filter="- *" \
 src target

编辑这个 shell 脚本相当容易,直到它产生一个很好的输出,-n这意味着“空运行”仅显示其意图。

当事情看起来正确时,您可以-n从两个命令行中删除并让它rsync做它的事情。或者也许您对文本输出感到满意,并将其保存到文件中或以某种方式将其通过管道传输到其他命令中(以执行 rsync 复制之外的其他操作)。

相关内容