我想递归地查找路径内的所有目录和文件,但想排除一些与给定模式匹配的其他目录和文件。然后我想对搜索结果执行进一步的命令,可能是cp
、mv
或rsync
的rm
结果find
。
假设我想要修剪整个node_modules
,.git
和build
目录以及修剪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
,那么您就做不到prune
。prune
意味着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
(假设--null
GNU实现或兼容) ,以便它们处理 NUL 分隔的输入。-0
grep
xargs
cut
sort
答案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 复制之外的其他操作)。