我不太明白'男人发现'给出的例子,有人能给我一些例子和解释吗?我可以在其中组合正则表达式吗?
更详细的问题是这样的:写一个shell脚本,changeall,它有一个像“changeall [-r | -R]”string1“”string2“这样的接口。它会找到所有后缀为.h的文件,。C,.cc或.cpp并将所有出现的“string1”更改为“string2”.- r是仅保留当前目录或包含subdir的选项。注意:1)对于非递归情况,'ls'是不允许的,我们只能使用'find'和'sed'。2)我试过'find -depth'但是它不受支持。这就是为什么我想知道'-prune'是否有帮助,但是不明白例如来自'man find'。
EDIT2:我正在做作业,我没有详细提问,因为我想自己完成。既然我已经完成并把它交给我,现在我可以陈述整个问题。此外,我设法在不使用-prune的情况下完成了作业,但无论如何都想学习它。
答案 0 :(得分:396)
我发现关于-prune
令人困惑的事情是它是一个动作(如-print
),而不是一个测试(如-name
)。它改变了“待办事项”列表,但始终返回true 。
使用-prune
的一般模式是:
find [path] [conditions to prune] -prune -o \
[your usual conditions] [actions to perform]
您几乎总是希望在-o
之后立即-prune
(逻辑OR),因为测试的第一部分(包括-prune
)将返回 false 用于你真正想要的东西(即:你不想要修剪掉的东西)。
以下是一个例子:
find . -name .snapshot -prune -o -name '*.foo' -print
这将找到不在“.snapshot”目录下的“* .foo”文件。在此示例中,-name .snapshot
组成[conditions to prune]
,-name '*.foo' -print
组成[your usual conditions]
和[actions to perform]
。
重要提示:
如果要打印结果,您可能会习惯忽略-print
操作。在使用-prune
时,您通常不想要这样做。
如果除了-print
(具有讽刺意味)之外没有其他操作,则find的默认行为是“和”整个表达式和-prune
操作。这意味着写下这个:
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
如果您的“常规条件”恰好与符合您修剪条件的文件相匹配,那么这些文件将不包含在输出中。解决此问题的方法是在剪枝条件中添加-type d
谓词。
例如,假设我们想要删除以.git
开头的任何目录(这无疑是有点人为的 - 通常你只需要删除名为的东西 {{1 }}),但除了想要查看所有文件,包括.git
等文件。你可以试试这个:
.gitignore
这将不在输出中包含find . -name '.git*' -prune -o -type f -print # DON'T DO THIS
。这是固定版本:
.gitignore
额外提示:如果您使用的是find . -type d -name '.git*' -prune -o -type f -print # DO THIS
的GNU版本,find
的texinfo页面的解释比其联机帮助页更详细(对于大多数GNU实用程序都是如此)。
答案 1 :(得分:26)
请注意-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
答案 2 :(得分:23)
通常我们在linux中做事的本地方式和我们思考的方式是从左到右 所以你会先写下你想要的东西:
find / -name "*.php"
然后你可能点击进入并意识到你收到了太多文件 你不希望的目录。 让我们排除/媒体以避免搜索您安装的驱动器 您现在应该将以下命令附加到上一个命令:
-print -o -path '/media' -prune
所以最后的命令是:
find / -name "*.php" -print -o -path '/media' -prune
............... |< ---包括---> | ................... 。|< ----------排除---------> |
我认为这种结构更容易,与正确的方法相关
答案 3 :(得分:9)
添加其他答案中给出的建议(我没有代表创建回复)...
将-prune
与其他表达式组合时,行为会有细微差别,具体取决于使用的其他表达式。
@Laurence Gonsalves的示例将找到不在“.snapshot”目录下的“* .foo”文件: -
find . -name .snapshot -prune -o -name '*.foo' -print
然而,这个略有不同的简写,也许是在无意中,也会列出.snapshot
目录(以及任何嵌套的.snapshot目录): -
find . -name .snapshot -prune -o -name '*.foo'
原因是(根据我系统的联机帮助页): -
如果给定的表达式不包含任何原色-exec, -ls,-ok或-print,给定的表达式有效地替换为:
(given_expression)-print
也就是说,第二个例子相当于输入以下内容,从而修改术语分组: -
find . \( -name .snapshot -prune -o -name '*.foo' \) -print
至少在Solaris 5.10上已经看到过这种情况。使用各种口味的* nix大约10年后,我最近才搜索出现这种情况的原因。
答案 4 :(得分:3)
Prune是一个不会在任何目录切换时递归。
来自手册页
如果没有给出-depth,则为true; 如果文件是目录,请不要进入该目录。 如果给出-depth,则为false;没有效果。
基本上它不会出现在任何子目录中。
举个例子:
您有以下目录
如果您运行find -name test2
:
它将返回两个目录
如果您运行find -name test2 -prune
:
它只会返回/ home / test2,因为它不会进入/ home / test2来查找/ home / test2 / test2
答案 5 :(得分:2)
我不是这方面的专家(此页面与http://mywiki.wooledge.org/UsingFind)
一起非常有用注意到-path
的路径是完全匹配find
之后的字符串/路径(在这些示例中为.
),其中{ {1}}匹配所有基本名称。
-name
阻止当前目录中的.git目录(,如find . -path ./.git -prune -o -name file -print
中的查找结果)
.
以递归方式阻止所有.git子目录。
注意find . -name .git -prune -o -name file -print
非常重要!! ./
必须与锚定到-path
的路径匹配,或者找到之后的任何内容(如果您与其匹配)(来自或.
的另一侧')可能没有被修剪!
我天真地没有意识到这一点,当你不想修剪所有具有相同基本名称的子目录时,它让我使用-path很好:D
答案 6 :(得分:1)
显示包括dir本身在内的所有内容,但不包括其冗长无聊的内容:
find . -print -name dir -prune
答案 7 :(得分:0)
如果你在这里阅读了所有好的答案,我现在的理解是以下所有答案都会返回相同的结果:
find . -path ./dir1\* -prune -o -print
find . -path ./dir1 -prune -o -print
find . -path ./dir1\* -o -print
#look no prune at all!
但最后一个会花费更长时间,因为它仍会搜索dir1中的所有内容。我想真正的问题是如何在没有实际搜索结果的情况下-or
输出不需要的结果。
所以我认为修剪意味着不要过去不错的比赛,但要把它标记为完成......
http://www.gnu.org/software/findutils/manual/html_mono/find.html &#34;然而,这不是由于'-prune'动作的影响(只能防止进一步下降,它不能确保我们忽略该项目)。相反,这种效果是由于使用'-o'。由于“或”条件的左侧成功为./src/emacs,因此根本不需要为此特定文件计算右侧(' - print')。&#34; < / p>
答案 8 :(得分:0)
find
建立文件列表。它将您提供的谓词应用于每个谓词,并返回通过的谓词。
这个-prune
意味着从结果中排除的想法确实让我感到困惑。您可以排除没有修剪的文件:
find -name 'bad_guy' -o -name 'good_guy' -print // good_guy
所有-prune
所做的都是改变搜索的行为。如果当前匹配项是目录,则其显示“嘿find
,您刚刚匹配的文件,请不要进入该文件” 。它只是从要搜索的文件列表中删除该树(而不是文件本身)。
应将其命名为-dont-descend
。
答案 9 :(得分:0)
有很多答案;其中有些过于理论化。我将离开为什么需要修剪一次,所以也许需求优先/示例这样的解释对某人有用:)
我有一个包含约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
时,您仍然可以进行标准的递归搜索。分析每个“路径”,吐出每个发现,find
像好家伙一样不断挖掘。但这是挖掘更多我不想要的node_modules
。
因此,区别在于,在任何不同的路径中,-prune
将find
在找到您的商品时停止进一步挖掘该特定途径。就我而言,是node_modules
文件夹。