繁体   English   中英

使用 find 命令但排除两个目录中的文件

[英]Use find command but exclude files in two directories

我想查找以_peaks.bed结尾的文件,但排除tmpscripts文件夹中的文件。

我的命令是这样的:

 find . -type f \( -name "*_peaks.bed" ! -name "*tmp*" ! -name "*scripts*" \)

但它没有用。 tmpscript文件夹中的文件仍将显示。

有人对此有想法吗?

以下是您如何使用find指定它的方法:

find . -type f -name "*_peaks.bed" ! -path "./tmp/*" ! -path "./scripts/*"

解释:

  • find . - 从当前工作目录开始查找(默认递归)
  • -type f - 指定find结果中只需要文件
  • -name "*_peaks.bed" - 查找名称以_peaks.bed结尾的_peaks.bed
  • ! -path "./tmp/*" ! -path "./tmp/*" - 排除所有路径以./tmp/开头的结果
  • ! -path "./scripts/*" ! -path "./scripts/*" - 同时排除所有路径以./scripts/开头的结果

测试解决方案:

$ mkdir a b c d e
$ touch a/1 b/2 c/3 d/4 e/5 e/a e/b
$ find . -type f ! -path "./a/*" ! -path "./b/*"

./d/4
./c/3
./e/a
./e/b
./e/5

您非常接近, -name选项仅考虑基本名称,而-path考虑整个路径 =)

这是你可以做到的一种方法......

find . -type f -name "*_peaks.bed" | egrep -v "^(./tmp/|./scripts/)"

采用

find \( -path "./tmp" -o -path "./scripts" \) -prune -o  -name "*_peaks.bed" -print

要么

find \( -path "./tmp" -o -path "./scripts" \) -prune -false -o  -name "*_peaks.bed"

要么

find \( -path "./tmp" -path "./scripts" \) ! -prune -o  -name "*_peaks.bed"

顺序很重要。 它从左到右评估。 总是从路径排除开始。

解释

不要使用-not (或! )来排除整个目录。 使用-prune 如手册中所述:

−prune    The primary shall always evaluate as  true;  it
          shall  cause  find  not  to descend the current
          pathname if it is a directory.  If  the  −depth
          primary  is specified, the −prune primary shall
          have no effect.

并在 GNU 查找手册中:

-path pattern
              [...]
              To ignore  a  whole
              directory  tree,  use  -prune rather than checking
              every file in the tree.

实际上,如果您使用-not -path "./pathname" , find 将计算"./pathname"下每个节点的表达式。

find 表达式只是条件评估。

  • \\( \\) - 分组操作(你可以使用-path "./tmp" -prune -o -path "./scripts" -prune -o ,但它更冗长)。
  • -path "./script" -prune - 如果-path返回 true 并且是一个目录,则为该目录返回 true 并且进入该目录。
  • -path "./script" ! -prune -path "./script" ! -prune - 它评估为(-path "./script") AND (! -prune) 它将 prune 的“始终为真”恢复为始终为假。 它避免将"./script"打印为匹配项。
  • -path "./script" -prune -false - 因为-prune总是返回 true,所以你可以用-false做同样的事情! .
  • -o - 或运算符。 如果两个表达式之间没有指定运算符,则默认为 AND 运算符。

因此, \\( -path "./tmp" -o -path "./scripts" \\) -prune -o -name "*_peaks.bed" -print扩展为:

[ (-path "./tmp" OR -path "./script") AND -prune ] OR ( -name "*_peaks.bed" AND print )

打印在这里很重要,因为没有它会扩展为:

{ [ (-path "./tmp" OR -path "./script" )  AND -prune ]  OR (-name "*_peaks.bed" ) } AND print

-print由 find 添加 - 这就是为什么大多数时候,您不需要在表达式中添加它。 由于-prune返回 true,它将打印“./script”和“./tmp”。

在其他情况下没有必要,因为我们将-prune切换为始终返回 false。

提示:您可以使用find -D opt expr 2>&1 1>/dev/null来查看它是如何优化和扩展的,
find -D search expr 2>&1 1>/dev/null以查看检查了哪个路径。

对我来说,这个解决方案在带有 find 的命令 exec 上不起作用,真的不知道为什么,所以我的解决方案是

find . -type f -path "./a/*" -prune -o -path "./b/*" -prune -o -exec gzip -f -v {} \;

说明:与 sampson-chen 相同,但添加了

-prune - 忽略...的处理路径

-o - 如果没有匹配,则打印结果,(修剪目录并打印剩余的结果)

18:12 $ mkdir a b c d e
18:13 $ touch a/1 b/2 c/3 d/4 e/5 e/a e/b
18:13 $ find . -type f -path "./a/*" -prune -o -path "./b/*" -prune -o -exec gzip -f -v {} \;

gzip: . is a directory -- ignored
gzip: ./a is a directory -- ignored
gzip: ./b is a directory -- ignored
gzip: ./c is a directory -- ignored
./c/3:    0.0% -- replaced with ./c/3.gz
gzip: ./d is a directory -- ignored
./d/4:    0.0% -- replaced with ./d/4.gz
gzip: ./e is a directory -- ignored
./e/5:    0.0% -- replaced with ./e/5.gz
./e/a:    0.0% -- replaced with ./e/a.gz
./e/b:    0.0% -- replaced with ./e/b.gz

你可以试试下面的:

find ./ ! \( -path ./tmp -prune \) ! \( -path ./scripts -prune \) -type f -name '*_peaks.bed'

尝试类似的东西

find . \( -type f -name \*_peaks.bed -print \) -or \( -type d -and \( -name tmp -or -name scripts \) -and -prune \)

如果我弄错了也不要太惊讶。 如果目标是 exec (而不是打印),只需将其替换到位。

通过这些解释,您可以实现您的目标和许多其他目标。 只需按照您的意愿加入每个部分。

模型

find ./\
 -iname "some_arg" -type f\ # File(s) that you want to find at any hierarchical level.
 ! -iname "some_arg" -type f\ # File(s) NOT to be found on any hirearchic level (exclude).
 ! -path "./file_name"\ # File(s) NOT to be found at this hirearchic level (exclude).
 ! -path "./folder_name/*"\ # Folder(s) NOT to be found on this Hirearchic level (exclude).
 -exec grep -IiFl 'text_content' -- {} \; # Text search in the content of the found file(s) being case insensitive ("-i") and excluding binaries ("-I").

例子

find ./\
 -iname "*" -type f\
 ! -iname "*pyc" -type f\
 ! -path "./.gitignore"\
 ! -path "./build/*"\
 ! -path "./__pycache__/*"\
 ! -path "./.vscode/*"\
 ! -path "./.git/*"\
 -exec grep -IiFl 'title="Brazil - Country of the Future",' -- {} \;

谢谢! 🤗🇧🇷

[参考文献: https://unix.stackexchange.com/q/73938/61742]


额外的:

您可以将上面的命令与您喜欢的编辑器一起使用并分析找到的文件的内容,例如...

vim -p $(find ./\
 -iname "*" -type f\
 ! -iname "*pyc" -type f\
 ! -path "./.gitignore"\
 ! -path "./build/*"\
 ! -path "./__pycache__/*"\
 ! -path "./.vscode/*"\
 ! -path "./.git/*"\
 -exec grep -IiFl 'title="Brazil - Country of the Future",' -- {} \;)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM