Search code examples
bashgrepfindescapinglanguage-lawyer

bash: How to use 'find' combined with '-exec grep' to search for an empty pair of braces


I know there are other ways to accomplish this, but I'm curious, bear with me.

I would like to search a directory tree for JSON manifest files containing the exact string: "submodules": {}, a result from a Jenkins pipeline.

I tried several combinations and found one that finds all for me relevant locations:

find . -type f -name *.json -exec grep -FHm 1 '"submodules": {' {} \;

This works, so my problem is solved.

But now I'm just curious: I know that {} has a special meaning for the find command. How can I rewrite that find command to look for "submodules": {}? The intuitive first try would be:

find . -type f -name *.json -exec grep -FHm 1 '"submodules": {}' {} \;

But even though the shell doesn't touch the search string because of the single-quotes, the find command has no such limitation, and the command finds nothing.

I tried several ways of quoting and escaping, but couldn't find a working combination. Anyone?


Solution

  • A solution using egrep/grep -E:

    find . -type f -name '*.json' -exec grep -EHm 1 '"submodules": \{\}' {} \;
    find . -type f -name '*.json' -exec egrep -Hm 1 '"submodules": \{\}' {} \;
    

    Using plain grep (without -F) by adding a redundant character class:

    find . -type f -name '*.json' -exec grep -Hm 1 '"submodules": [{]}' {} \;
    

    You could also create a file to run grep for you, e.g. grep.sh:

    cat > grep.sh <<SH
    #!/bin/sh
    grep -FHm 1 '"submodules": {}' "$@"
    SH
    chmod +x grep.sh
    

    then execute the script file via find:

    find . -type f -name '*.json' -exec ./grep.sh {} \;