如何在sh中使用'find'的'-prune'选项?
我不太明白“男人找”的例子,谁能给我一些例子和解释? 我可以结合正则expression式吗?
更详细的问题是这样的:编写一个shell脚本changeall,它有一个像“changeall [-r | -R]”string1“”string2“这样的接口,它将find所有具有.h,.C ,.cc或.cpp,并将所有出现的“string1”更改为“string2”。-r是仅保留在当前dir或包括subdir的选项。注意:1)对于非recursion情况,不允许使用“ls” ,我们只能使用'find'和'sed'2)我试过了'find -depth'但是不支持,所以我想知道'-prune'是否可以帮忙,但是不明白'男人find'。
编辑2:我在做任务,我没有提出很详细的问题,因为我想自己完成。 既然我已经把它交了,现在我可以说出整个问题。 另外,我设法完成了任务,而不使用-prune,但仍想学习它。
我发现令人困惑的事情是,这是一个动作(像-print
),而不是testing(像-name
)。 它改变了“待办事项”列表, 但总是返回true 。
使用-prune
的一般模式是这样的:
find [path] [conditions to prune] -prune -o \ [your usual conditions] [actions to perform]
你几乎总是想在-prune
之后立即使用-o
,因为testing的第一部分(包括-prune
)将会为你实际需要的东西返回false (即:你不想修剪的东西)。
这是一个例子:
find . -name .snapshot -prune -o -name '*.foo' -print
这将find不在“.snapshot”目录下的“* .foo”文件。 在这个例子中, -name .snapshot
是“要修剪的东西的testing”,而-name '*.foo' -print
是“通常放在path后面的东西”。
重要提示 :
-
如果你所要做的只是打印你可能会用来排除
-print
操作的结果。 在使用-prune
时,您通常不希望这样做。find的默认行为是如果在最后没有除
-prune
(具有讽刺意味的)以外的其他操作,则使用-print
操作来“和” 整个expression式。 这意味着写这个: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
开头的任何目录(这当然是有些人为的 – 通常你只需要删除名为.git
东西),但.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
,那么find
的texinfo页面比它的manpage有更详细的解释(对于大多数GNU工具来说)。
请注意,普隆不能像有些人所说的那样阻止进入任何目录。 它可以防止降序到与应用testing相匹配的目录。 也许一些例子会有所帮助(见正则expression式的底部)。 对不起,这太冗长了。
$ 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
通常情况下,我们在linux上做的事情是我们自己的方式,我们认为是从左到右。
所以你会先写下你要找的东西:
find / -name "*.php"
那么你可能会打进来,并意识到你从你不希望的目录得到太多的文件。 让我们排除/媒体,以避免search您的安装的驱动器。
您现在只需将以下命令添加到上一个命令:
-print -o -path '/media' -prune
所以最后的命令是:
find / -name "*.php" -print -o -path '/media' -prune
…………… | <—包括—> | ……………….. | < – ——–排除———> |
我认为这个结构要容易得多,而且要和正确的方法联系起来
添加到其他答案给出的build议(我没有代表创build答复)…
当将-prune
与其他expression式组合在一起时,行为之间会有细微的差别,这取决于使用哪个expression式。
@Laurence Gonsalves的例子会find不在“.snapshot”目录下的“* .foo”文件:
find . -name .snapshot -prune -o -name '*.foo' -print
然而,这个略有不同的短手也许会不经意地列出.snapshot
目录(以及任何嵌套的.snapshot目录):
find . -name .snapshot -prune -o -name '*.foo'
原因是(根据我的系统的手册):
如果给定的expression式不包含任何主要的-exec,-ls,-ok或-print,则给定的expression式可以有效地被replace为:
(given_expression)–print
也就是说,第二个例子相当于input以下内容,从而修改了术语的分组:
find . \( -name .snapshot -prune -o -name '*.foo' \) -print
至less在Solaris 5.10上可以看到这一点。 使用了各种口味的* nix大约10年,我最近才find一个为什么发生这种情况的原因。
Prune在任何目录切换时都不会递减。
从手册页
如果没有给出深度,则为真; 如果文件是一个目录,不要下载到它。 如果-depth被给出,则为false; 没有效果。
基本上它不会放入任何子目录。
以这个例子:
你有以下的目录
- /家/ TEST2
- /家庭/ TEST2 / TEST2
如果你运行find -name test2
:
它会返回这两个目录
如果你运行find -name test2 -prune
:
它将只返回/ home / test2,因为它不会下到/ home / test2中find/ home / test2 / test2
我不是这方面的专家(并且这个网页与http://mywiki.wooledge.org/UsingFind一起非常有帮助);
刚才注意到-path
是一个完全匹配的string/path,就像-name
(在这个例子中),其中as -name
匹配所有的基本名称。
find . -path ./.git -prune -o -name file -print
阻止当前目录中的.git目录(如发现英寸)
find . -name .git -prune -o -name file -print
以recursion方式阻塞所有的.git子目录。
注意./
是非常重要的! -path
必须匹配锚定到的path.
或任何后来发现,如果你得到匹配(或“ -o
”的另一边),可能没有被修剪! 我天真地没有意识到这一点,它使我使用-path,当你不想修剪所有具有相同的基本名称的子目录:D
显示包括dir本身在内的所有内容,但不包含冗长的无聊内容:
find . -print -name dir -prune
如果你在这里读到所有的好答案,我现在的理解是,以下所有的结果都返回相同的结果:
find . -path ./dir1\* -prune -o -print find . -path ./dir1 -prune -o -print find . -path ./dir1\* -o -print #look no prune at all!
但是最后一个将花费更长的时间,因为它仍然searchdir1中的所有内容。 我想真正的问题是如何去实现不需要的结果,而不用实际search它们。
所以我觉得修剪意味着不适合过去的比赛,但将其标记为完成…
http://www.gnu.org/software/findutils/manual/html_mono/find.html “然而,这不是由于”普隆“行动的影响(它只能防止进一步的下降,它不能确保我们忽略了这个项目),而是这个效果是由于使用了'-o',因为“或”条件的左边成功了./src/emacs,所以没有必要去评估右边的项目,手边('印')在这个特定的文件。