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


更详细的问题是这样的:

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

注意:

对于非递归的情况,ls是不允许的,我们只能使用find和sed。 我尝试寻找深度,但它不支持。这就是为什么我想知道-prune是否可以帮助,但不理解从man find的例子。


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


修剪是一个“不递归此文件”开关(操作)。

从手册页

如果-depth未指定,则为true; 如果文件是一个目录,不要进入它。 如果给出了-depth,则为false;没有效果。

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

举个例子:

您有以下目录:

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

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

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

现在,用-西梅…

找到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]

你总是想在-prune之后立即使用-o(逻辑或),因为测试的第一部分(直到并包括-prune)对于你真正想要的东西(即:你不想修剪的东西)将返回false。

这里有一个例子:

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

这将找到“*”。Foo“文件不在下面”。快照”目录。在本例中,name .snapshot组成[修剪的条件],name '*。Foo ' -print是[您通常的条件]和[要执行的操作]。

重要提示:

If all you want to do is print the results you might be used to leaving out the -print action. You generally don't want to do that when using -prune. The default behavior of find is to "and" the entire expression with the -print action if there are no actions other than -prune (ironically) at the end. That means that writing this: find . -name .snapshot -prune -o -name '*.foo' # DON'T DO THIS is equivalent to writing this: find . \( -name .snapshot -prune -o -name '*.foo' \) -print # DON'T DO THIS which means that it'll also print out the name of the directory you're pruning, which usually isn't what you want. Instead it's better to explicitly specify the -print action if that's what you want: find . -name .snapshot -prune -o -name '*.foo' -print # DO THIS If your "usual condition" happens to match files that also match your prune condition, those files will not be included in the output. The way to fix this is to add a -type d predicate to your prune condition. For example, suppose we wanted to prune out any directory that started with .git (this is admittedly somewhat contrived -- normally you only need to remove the thing named exactly .git), but other than that wanted to see all files, including files like .gitignore. You might try this: find . -name '.git*' -prune -o -type f -print # DON'T DO THIS This would not include .gitignore in the output. Here's the fixed version: find . -name '.git*' -type d -prune -o -type f -print # DO THIS

额外提示:如果您使用的是find的GNU版本,那么find的texinfo页面比它的manpage有更详细的解释(大多数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“文件不在下面”。快照”目录:-

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

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

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

根据posix manpage,原因是:

如果给定的表达式不包含任何主-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(后面的字符串/path的路径。在这些例子中),其中as -name匹配所有的基名。

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

阻塞当前目录中的.git目录(就像你在。目录中找到的一样)

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

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

注意。/是非常重要的!!-path必须匹配锚定到的路径。或者在find之后出现的任何东西,如果你匹配了它(从或'-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中的所有内容。我想真正的问题是如何在不实际搜索的情况下删除不需要的结果。

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

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


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

find . -print -name dir -prune

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

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

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

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

它应该被命名为-don - descent。


答案有很多;有些书的理论内容太多了。我会留下为什么我需要修剪一次,所以也许需求优先/例子类型的解释对某人有用:)

问题

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

一旦进入任何项目,就会看到每个../node_modules/module。但你知道是怎么回事。几乎每个模块都有依赖关系,所以你看到的更像是projectN/node_modules/ modulelex /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时,仍然会有一个标准的递归搜索。每条“路径”都会被分析,每一个发现都会被抛出,而find会像一个好人一样继续深入挖掘。但是,深入挖掘更多的node_modules是我不想要的。

所以,不同之处在于,在这些不同的路径中,-prune会发现,当它找到你的项目时,它会停止在特定的道路上进一步挖掘。在我的例子中,是node_modules文件夹。