Unix Command to List files containing string but *NOT* containing another string

后端 未结 6 1725
春和景丽
春和景丽 2021-01-30 22:01

How do I recursively view a list of files that has one string and specifically doesn\'t have another string? Also, I mean to evaluate the text of the files, not the filenames.

相关标签:
6条回答
  • 2021-01-30 22:30

    Try this:

    grep -rl <string-to-match> | xargs grep -L <string-not-to-match>
    

    Explanation: grep -lr makes grep recursively (r) output a list (l) of all files that contain <string-to-match>. xargs loops over these files, calling grep -L on each one of them. grep -L will only output the filename when the file does not contain <string-not-to-match>.

    0 讨论(0)
  • 2021-01-30 22:37

    These answers seem off as the match BOTH strings. The following command should work better:

    grep -l <string-to-match> * | xargs grep -c <string-not-to-match> | grep '\:0'
    
    0 讨论(0)
  • 2021-01-30 22:37

    To match string A and exclude strings B & C being present in the same line I use, and quotes to allow search string to contain a space

    grep -r <string A> | grep -v -e <string B> -e "<string C>" | awk -F ':' '{print $1}'
    

    Explanation: grep -r recursively filters all lines matching in output format

    filename: line

    To exclude (grep -v) from those lines the ones that also contain either -e string B or -e string C. awk is used to print only the first field (the filename) using the colon as fieldseparator -F

    0 讨论(0)
  • 2021-01-30 22:40

    find . -maxdepth 1 -name "*.py" -exec grep -L "string-not-to-match" {} \;

    This Command will get all ".py" files that don't contain "string-not-to-match" at same directory.

    0 讨论(0)
  • 2021-01-30 22:49

    Here is a more generic construction:

    find . -name <nameFilter> -print0 | xargs -0 grep -Z -l <patternYes> | xargs -0 grep -L <patternNo>
    

    This command outputs files whose name matches <nameFilter> (adjust find predicates as you need) which contain <patternYes>, but do not contain <patternNo>.

    The enhancements are:

    • It works with filenames containing whitespace.
    • It lets you filter files by name.

    If you don't need to filter by name (one often wants to consider all the files in current directory), you can strip find and add -R to the first grep:

    grep -R -Z -l <patternYes> | xargs -0 grep -L <patternNo>
    
    0 讨论(0)
  • 2021-01-30 22:53

    The use of xargs in the answers above is not necessary; you can achieve the same thing like this:

    find . -type f -exec grep -q <string-to-match> {} \; -not -exec grep -q <string-not-to-match> {} \; -print
    

    grep -q means run quietly but return an exit code indicating whether a match was found; find can then use that exit code to determine whether to keep executing the rest of its options. If -exec grep -q <string-to-match> {} \; returns 0, then it will go on to execute -not -exec grep -q <string-not-to-match>{} \;. If that also returns 0, it will go on to execute -print, which prints the name of the file.

    As another answer has noted, using find in this way has major advantages over grep -Rl where you only want to search files of a certain type. If, on the other hand, you really want to search all files, grep -Rl is probably quicker, as it uses one grep process to perform the first filter for all files, instead of a separate grep process for each file.

    0 讨论(0)
提交回复
热议问题