'-prune'选项'查找'在上海吗?

我不太理解man find给出的例子,谁能给我一些例子和解释?我可以在里面结合正则表达式吗?


更详细的问题是这样的:

写一个shell脚本changeall,它有一个类似changeall [-r|-R] "string1" "string2"的接口。它将找到所有后缀为.h.C.cc.cpp的文件,并将所有出现的string1更改为string2-r是仅保留当前目录或包含子目录的选项。

注意:

  1. 对于非递归情况,ls是不允许的,我们只能使用findsed
  2. 我尝试了find -depth,但它不支持。这就是为什么我想知道-prune是否可以帮助,但不理解来自man find的例子。

EDIT2:我在做作业,我没有问太多细节,因为我想自己完成。既然我已经做完并交上来了,现在我可以陈述整个问题了。另外,我在没有使用-prune的情况下完成了作业,但无论如何我都想学习它。

141682 次浏览

修剪是一个“不递归此文件”;开关(行动)。

从手册页

如果-depth没有给出,则为true; 如果文件是一个目录,不要进入它。 如果给出了-depth,则为false;没有影响。< / p >

基本上它不会下降到任何子目录。

举个例子:

您有以下目录:

% find home
home
home/test1
home/test1/test1
home/test2
home/test2/test2

find home -name test2将打印父目录和名为test2的子目录:

% find home -name test2
home/test2
home/test2/test2

现在,通过修剪

find home -name test2 -prune将只打印/home/test2;它不会潜入/home/test2找到/home/test2/test2:

% find home -name test2 -prune
home/test2

我对-prune感到困惑的是,它是一个动作(像-print),而不是一个测试(像-name)。它改变了&;to; do;列表,但总是返回true

使用-prune的一般模式是:

find [path] [conditions to prune] -prune -o \
[your usual conditions] [actions to perform]

你几乎总是希望-o(逻辑或)紧跟在-prune之后,因为测试的第一部分(直到并包括-prune)将返回你真正想要的东西的(即:你想要删除的东西)。

这里有一个例子:

find . -name .snapshot -prune -o -name '*.foo' -print

这将会找到"*.foo"不在“。snapshot”目录下的文件;目录。在这个例子中,-name .snapshot组成了[conditions to prune],而-name '*.foo' -print[your usual conditions][actions to perform]

重要的笔记:

  1. 如果你想要做的只是打印结果,你可能习惯于省略-print操作。在使用-prune时,通常希望这样做。

    find的默认行为是"和"如果结束时除了-prune(具有讽刺意味)之外没有其他动作,则返回带有-print动作的整个表达式。这意味着要这样写:

     find . -name .snapshot -prune -o -name '*.foo'              # DON'T DO THIS
    

    等价于这样写

     find . \( -name .snapshot -prune -o -name '*.foo' \) -print # DON'T DO THIS
    

    这意味着它还会打印出您正在修剪的目录的名称,这通常不是您想要的。相反,如果这是你想要的,最好显式地指定-print动作:

     find . -name .snapshot -prune -o -name '*.foo' -print       # DO THIS
    
  2. 如果你的“正常状况”;恰巧匹配的文件也匹配你的修剪条件,这些文件将包含在输出中。解决这个问题的方法是在你的prune条件中添加一个-type d谓词。

    例如,假设我们想要删除任何以.git开头的目录(这确实有点刻意——通常你只需要删除名为完全 .git的东西),但除此之外,我们想要查看所有文件,包括像.gitignore这样的文件。你可以试试这个:

    find . -name '.git*' -prune -o -type f -print               # DON'T DO THIS
    

    这将在输出中包含.gitignore。以下是固定版本:

    find . -name '.git*' -type d -prune -o -type f -print       # DO THIS
    

额外提示:如果你使用的是find的GNU版本,find的texinfo页面有一个比它的手册页更详细的解释(大多数GNU实用程序都是如此)。

注意-prune并不能防止像一些人说的那样下降到任何目录。它可以防止下降到与应用它的测试匹配的目录。也许一些例子会有所帮助(参见下面的正则表达式示例)。抱歉这么长时间。

$ find . -printf "%y %p\n"    # print the file type the first time FYI
d .
f ./test
d ./dir1
d ./dir1/test
f ./dir1/test/file
f ./dir1/test/test
d ./dir1/scripts
f ./dir1/scripts/myscript.pl
f ./dir1/scripts/myscript.sh
f ./dir1/scripts/myscript.py
d ./dir2
d ./dir2/test
f ./dir2/test/file
f ./dir2/test/myscript.pl
f ./dir2/test/myscript.sh


$ find . -name test
./test
./dir1/test
./dir1/test/test
./dir2/test


$ find . -prune
.


$ find . -name test -prune
./test
./dir1/test
./dir2/test


$ find . -name test -prune -o -print
.
./dir1
./dir1/scripts
./dir1/scripts/myscript.pl
./dir1/scripts/myscript.sh
./dir1/scripts/myscript.py
./dir2


$ find . -regex ".*/my.*p.$"
./dir1/scripts/myscript.pl
./dir1/scripts/myscript.py
./dir2/test/myscript.pl


$ find . -name test -prune -regex ".*/my.*p.$"
(no results)


$ find . -name test -prune -o -regex ".*/my.*p.$"
./test
./dir1/test
./dir1/scripts/myscript.pl
./dir1/scripts/myscript.py
./dir2/test


$ find . -regex ".*/my.*p.$" -a -not -regex ".*test.*"
./dir1/scripts/myscript.pl
./dir1/scripts/myscript.py


$ find . -not -regex ".*test.*"                   .
./dir1
./dir1/scripts
./dir1/scripts/myscript.pl
./dir1/scripts/myscript.sh
./dir1/scripts/myscript.py
./dir2

添加到其他答案中给出的建议(我没有代表创建回复)…

当将-prune与其他表达式组合使用时,根据使用的其他表达式,行为会有细微的差异。

@Laurence Gonsalves的例子会发现"*.foo"不在“。snapshot”目录下的文件;目录:

find . -name .snapshot -prune -o -name '*.foo' -print

然而,这个略有不同的简写也会列出.snapshot目录(以及任何嵌套的.snapshot目录):-

find . -name .snapshot -prune -o -name '*.foo'

根据posix从,原因是:

如果给定的表达式不包含任何primary -exec, -ls, -ok,或-print,则指定表达式有效地替换为:

(given_expression) -打印

也就是说,第二个示例相当于输入以下内容,从而修改术语的分组:-

find . \( -name .snapshot -prune -o -name '*.foo' \) -print

至少在Solaris 5.10上可以看到这一点。在使用了大约10年的各种*nix之后,我最近才开始寻找出现这种情况的原因。

通常,我们在Linux中做事的原生方式,以及我们思考的方式,是从左到右的。

你可以先写下你想要的东西:

find / -name "*.php"

然后,您按下ENTER键,并意识到您从不想获取的目录中获取了太多文件。

因此,您认为“让我们排除/media以避免搜索已挂载的驱动器”;

现在你只需将下面的附加添加到前面的命令中:

-print -o -path '/media' -prune

最后一个命令是:

find / -name "*.php" -print -o -path '/media' -prune
|<--      Include      -->|<--      Exclude      -->|

我认为这种结构要简单得多,而且与正确的方法相关。

我不是这方面的专家(这一页与http://mywiki.wooledge.org/UsingFind一起非常有用)

刚刚注意到-path是用于完全匹配find后面的字符串/路径(在这些例子中是.)的路径,其中-name匹配所有的基名。

find . -path ./.git  -prune -o -name file  -print

将当前目录中的.git目录阻塞为你在. 中找到的

find . -name .git  -prune -o -name file  -print

递归地阻塞所有.git子目录。

注意./是非常重要的!!-path必须匹配一个锚定到. 或者跟在“发现”后面的的路径,如果你没有匹配它(从'-o'的另一边),可能没有被修剪! 我很天真地没有意识到这一点,它让我使用-path当它是伟大的,当你不想修剪所有子目录与相同的basename:D

如果你读了这里所有的好答案,我现在的理解是,以下都返回相同的结果:

find . -path ./dir1\*  -prune -o -print


find . -path ./dir1  -prune -o -print


find . -path ./dir1\*  -o -print
#look no prune at all!

最后一个将花费更长的时间,因为它仍然搜索dir1中的所有内容。我想真正的问题是如何-or出不需要的结果,而不实际搜索他们。

所以我猜prune的意思是不要美化过去的比赛,而是把它标记为已经完成…

http://www.gnu.org/software/findutils/manual/html_mono/find.html “然而,这并不是由于‘修剪’动作的影响(它只是防止进一步下降,并不能确保我们忽略该项目)。相反,这种效果是由于使用了' -o '。由于./src/emacs的" or "条件左边已经成功,因此对于这个特定的文件,根本没有必要计算右边(' -print ')。" < / p >

显示所有内容,包括dir本身,但不显示其冗长乏味的内容:

find . -print -name dir -prune

find构建一个文件列表。它将您提供的谓词应用到每个谓词,并返回通过的谓词。

-prune的意思是排除在结果之外,这个想法真的让我很困惑。你可以排除一个文件不修剪:

find -name 'bad_guy' -o -name 'good_guy' -print  // good_guy

所有-prune所做的就是改变搜索行为。如果当前匹配的是一个目录,则表示“嘿find,你刚刚匹配的那个文件,不要进入它”。它只是从要搜索的文件列表中删除该树(而不是文件本身)。

它应该被命名为-dont-descend

答案有很多;有些书的理论内容太多了。我将留下为什么我需要西梅一次,所以可能首先需要/例子类型的解释对某些人有用:)

问题

我有一个包含大约20个节点目录的文件夹,每个目录都有node_modules目录。

一旦你进入任何项目,你会看到每个../node_modules/module。但你知道是怎么回事。几乎每个模块都有依赖项,所以你看到的更像是projectN/node_modules/moduleX/node_modules/moduleZ...

我不想被一堆依赖的东西淹没

知道-d n / -depth n,这对我没有帮助,因为我想要的每个项目的main/first node_modules目录处于不同的深度,就像这样:

Projects/MysuperProjectName/project/node_modules/...
Projects/Whatshisname/version3/project/node_modules/...
Projects/project/node_modules/...
Projects/MysuperProjectName/testProject/november2015Copy/project/node_modules/...
[...]

我怎么能得到第一个路径列表结束在第一个node_modules和移动到下一个项目得到相同的?

进入-prune

当你添加-prune时,你仍然有一个标准的递归搜索。每个“path"被分析,每一个发现都被吐出来,而find继续像一个好人一样深入挖掘。但这是对更多node_modules的挖掘,我不想要。

因此,不同之处在于,在任何这些不同的路径中,-prunefind停止进一步挖掘特定的路径,当它找到你的项目时。在我的例子中,是node_modules文件夹。