如何在sh中使用'find'的'-prune'选项? [英] How to use '-prune' option of 'find' in sh?

查看:179
本文介绍了如何在sh中使用'find'的'-prune'选项?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不太明白男人找的例子,谁能给我一些例子和解释?我可以结合正则表达式吗?



更详细的问题是这样的:编写一个shell脚本changeall,它有一个像changeall [ r | -R]string1string2,它将查找所有带.h,.C,.cc或.cpp后缀的文件,并将所有出现的string1更改为string2。注意:1)对于非递归的情况,'ls'是不允许的,我们只能使用'find'和'sed'。2)我尝试了'find -depth'不支持,这就是为什么我想知道'-prune'是否可以帮助,但是不理解'man find'的例子。
$ b $ hr

编辑2:我在做任务,我没有很好的提问,因为我想自己完成,因为我已经完成了,现在我可以说出整个问题。 ,我设法完成了任务,而不使用-prune,但仍然想学习它。

-prune 是一个动作(像 -print ),而不是测试(如 -name )。它改变了待办事项清单,但总是返回true


$ b 使用 -prune的一般模式



  find [path] [修剪条件] -prune -o \ 
[你平常的情况] [执行的动作]

你几乎总是希望 -o 紧接在 -prune 之后,因为测试的第一部分(最多包括 - prune )将会返回 false 作为你实际需要的东西(即:你不想删除的东西)。



下面是一个例子:

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

这会找到不在.snapshot目录下的* .foo文件。在这个例子中, -name .snapshot 是你要修剪的东西的测试, -name'* .foo'-print 是通常放在路径后面的东西。



重要注意事项


  1. 如果您只想打印可能用于省略 -print -prune 时,通常不要 如果除了之外没有任何动作,find的默认行为是使用 -print 动作的整个 (具有讽刺意味的是)在最后。这意味着写这个:

      find。 -name.snapshot -prune -o -name'* .foo'#不要这样做

    相当于写这个:

      find。 \(-name .snapshot -prune -o -name'* .foo'\)-print#不要这样做

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

      find。 -name .snapshot -prune -o -name'* .foo'-print#做这个


  2. <如果你的平常条件恰好匹配了与你的修剪条件相匹配的文件,那么这些文件就不会被包含在输出中。解决这个问题的方法是在修剪条件中添加一个 -type d 谓词。

    例如,假设我们希望删除以 .git 开头的任何目录(这是无可厚非的 - 通常你只需要正确删除名为的东西 code> .git
    ),但除此之外,希望查看所有文件,包括像 .gitignore 这样的文件。你可以试试这个:

      find。 -name'.git *'-prune -o -type f -print#不要这样做

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

      find。 -type d -name'.git *'-prune -o -type f -print#做这个


  3. 特别提示:如果您使用 find 的GNU版本,那么的texinfo页面找到比它的manpage有更详细的解释(对于大多数GNU工具来说都是如此)。

    I don't quite understand the example given from the 'man find', can anyone give me some examples and explanations? Can I combine regular expression in it?


    the more detailed question is like this: write a shell script, changeall, which has an interface like "changeall [-r|-R] "string1" "string2". It will find all files with an suffix of .h, .C, .cc, or .cpp and change all occurrences of "string1" to "string2". -r is option for staying in current dir only or including subdir's. NOTE: 1) for non-recursive case, 'ls' is NOT allowed, we could only use 'find' and 'sed'. 2) I tried 'find -depth' but it was NOT supported. That's why I was wondering if '-prune' could help, but didn't understand the example from 'man find'.


    EDIT2: I was doing assignment, I didn't ask question in great details because I would like to finish it myself. Since I already done it and hand it in, now I can state the whole question. Also, I managed to finish the assignment without using -prune, but would like to learn it anyway.

    解决方案

    The thing I'd found confusing about about -prune is that it's an action (like -print), not a test (like -name). It alters the "to-do" list, but always returns true.

    The general pattern for using -prune is this:

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

    You pretty much always want the the -o immediately after -prune, because that first part of the test (up to including -prune) will return false for the stuff you actually want (ie: the stuff you don't want to prune out).

    Here's an example:

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

    This will find the "*.foo" files that aren't under ".snapshot" directories. In this example, -name .snapshot is the "tests for stuff you want to prune", and -name '*.foo' -print is the "stuff you'd normally put after the path".

    Important notes:

    1. 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
      

    2. 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 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 . -type d -name '.git*' -prune -o -type f -print       # DO THIS
      

    Extra tip: if you're using the GNU version of find, the texinfo page for find has a more detailed explanation than its manpage (as is true for most GNU utilities).

    这篇关于如何在sh中使用'find'的'-prune'选项?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆