2

I have a directory named dir1 which has about 800 sub-directories named disp-001, disp-002, ... disp-800. I need to find sub-directories that

  • either do not contain a file stdout or
  • if they do, that file does not contain a particular string str1.

Identifying sub-directories that do not contain the file is answered in another question

$ find . -type d \! -exec test -e '{}/stdout' \; -print

However if I try to include grep in the above command, it does not work

 $ find . -type d \! -exec test -e 'grep str1 {}/stdout' \; -print

How can I include the string search to return me the directory of interest?

4

You can adapt any of the solutions there, e.g.

  • use ( -exec or -exec ) with slm's or patrick's solutions (the second exec is executed only if the first one returns false, -print is executed only if one of them returns true):

    find . -type d \( ! -exec test -f '{}/stdout' \; -o ! -exec grep -q str1 '{}/stdout' \; \) -print
    

    or even shorter as suggested by Costas:

    find . -type d \! -exec grep -q 'str1' {}/stdout 2>/dev/null \; -print
    
  • use a condition with terdon's solution:

    for d in **/
    do
      if [[ ! -f "$d"stdout ]] then
        printf '%s\n' "$d"
      else
        grep -q str1 "$d"stdout || printf '%s\n' "$d"
      fi
    done
    
  • or, with zsh:

    print -rl **/*(/e_'[[ ! -f $REPLY/stdout ]] || ! grep -q str1 $REPLY/stdout'_)
    
  • You can avoid extra test find . -type d \! -exec grep -q 'str1' {}/stdout 2>/dev/null \; -print – Costas Sep 23 '15 at 20:27
  • @Costas - you're right, I misunderstood the question... I'll edit my answer... Thanks for the heads-up ! – don_crissti Sep 23 '15 at 20:34
2

To get that list just use grep:

grep -L str1 dir-*/stdout

Where:

  • -L gives only the file without a match.
  • str1 is the string you want to search.
  • And if your files are in the same depth you can use simple wildcards.
    • If not, use the -r flag of grep to search recusively in the directories.

To continue that and work on that list you could pipe it nullbyte-delimited (greps -Z) to a while loop:

grep -LZ str1 dir-*/stdout | while IFS= read -r -d '' f; do
  echo "${f%%/*}" # gives the directory name
done

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.