Excluding subdirectories using the find command

This question already has an answer here:

  • How to exclude a directory in find . command 32 answers

  • Following my previous comment, this works on my Debian :

    find . -path ./ignored_directory -prune -o -name fileName.txt -print
    

    or

    find /path/to/folder -path "*/ignored_directory" -prune -o -name fileName.txt -print
    

    or

    find /path/to/folder -name fileName.txt -not -path "*/ignored_directory/*"
    

    The differences are nicely debated here


    To complement olivm's helpful answer and address the OP's puzzlement at the need for -o :

  • -prune , as every find primary (action or test, in GNU speak), returns a Boolean, and that Boolean is always true in the case of -prune .
  • Without explicit operators, primaries are implicitly connected with -a ( -and ), which, like its brethren -o ( -or ) performs short-circuiting Boolean logic.
  • -a has higher precedence than -o .
  • For a summary of all find concepts, see https://stackoverflow.com/a/29592349/45375

    Thus, the accepted answer ,

    find . -path ./ignored_directory -prune -o -name fileName.txt -print
    

    is equivalent to (parentheses are used to make the evaluation precedence explicit):

    find . ( -path ./ignored_directory -a -prune ) 
           -o 
           ( -name fileName.txt -a -print )
    

    Since short-circuiting applies, this is evaluated as follows:

  • an input path matching ./ignored_directory causes -prune to be evaluated; since -prune always returns true , short-circuiting prevents the right side of the -o operator from being evaluated; in effect, nothing happens (the input path is ignored)
  • an input path NOT matching ./ignored_directory , instantly - again due to short-circuiting - continues evaluation on the right side of -o :
  • only if the filename part of the input path matches fileName.txt is the -print primary evaluated; in effect, only input paths whose filename matches fileName.txt are printed.
  • Edit : In spite of what I originally claimed here, -print IS needed on the right-hand side of -o here; without it, the implied -print would apply to the entire expression and thus also print for left-hand side matches; see below for background information.


    By contrast, let's consider what mistakenly NOT using -o does :

    find . -path ./ignored_directory -prune -name fileName.txt -print
    

    This is equivalent to:

    find . -path ./ignored_directory -a -prune -a -name fileName.txt -a -print
    

    This will only print pruned paths (that also match the -name filter), because the -name and -print primaries are (implicitly) connected with logical ANDs;
    in this specific case, since ./ignored_directory cannot also match fileName.txt , nothing is printed, but if -path 's argument is a glob, it is possible to get output.


    A word on find 's implicit use of -print :

    POSIX mandates that if a find command's expression as a WHOLE does NOT contain either

  • output-producing primaries, such as -print itself
  • primaries that execute something, such as -exec and -ok
  • (the example primaries given are exhaustive for the POSIX spec. of find , but real-world implementations such as GNU find and BSD find add others, such as the output-producing -print0 primary, and the executing -execdir primary)
  • that -print be applied implicitly, as if the expression had been specified as:

    ( expression ) -print

    This is convenient, because it allows you to write commands such as find . , without needing to append -print .

    However, in certain situations an explicit -print is needed , as is the case here:

    Let's say we didn't specify -print at the end of the accepted answer:

    find . -path ./ignored_directory -prune -o -name fileName.txt
    

    Since there's now no output-producing or executing primary in the expression, it is evaluated as:

    find . ( -path ./ignored_directory -prune -o -name fileName.txt ) -print
    

    This will NOT work as intended, as it will print paths if the entire parenthesized expression evaluates to true, which in this case mistakenly includes the pruned directory.

    By contrast, by explicitly appending -print to the -o branch, paths are only printed if the right-hand side of the -o expression evaluates to true; using parentheses to make the logic clearer:

    find . -path ./ignored_directory -prune -o ( -name fileName.txt -print )
    

    If, by contrast, the left-hand side is true, only -prune is executed, which produces no output (and since the overall expression contains a -print , -print is NOT implicitly applied).


    Edit (added behavior specification details)

    Pruning all permission denied directories in find

    Using gnufind.

    Specification behavior details - in this solutions we want to:

  • exclude unreadable directories contents (prune them),
  • avoid "permission denied" errors coming from unreadable dierctory,
  • keep the other errors and return states, but
  • process all files (even unreadable files, if we can read their names)
  • The basic design pattern is:

    find ...  ( -readable -o -prune ) ...
    

    Example

    find /var/log/ ( -readable -o -prune ) -name "*.1" 
    

    thanks{mklement0}

    链接地址: http://www.djcxy.com/p/78124.html

    上一篇: 忽略find中的目录路径(在shell中)

    下一篇: 使用find命令排除子目录