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


更详细的问题是这样的:

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

注意:

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


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


当前回答

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

问题

我有一个包含大约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文件夹。

其他回答

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

find . -print -name dir -prune

注意,-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感到困惑的是,它是一个操作(如-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实用程序都是如此)。

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

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

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

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

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

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

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

find / -name "*.php"

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

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

现在你只需要将以下内容添加到前面的命令中:

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

最后一个命令是:

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

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