Identifique os subdiretórios que não contêm uma cadeia específica em um arquivo específico

2

Eu tenho um diretório chamado dir1 que tem cerca de 800 subdiretórios chamados disp-001, disp-002, ... disp-800 . Eu preciso encontrar subdiretórios que

  • ou não contêm um arquivo stdout ou
  • se o fizerem, esse arquivo não contém uma string específica str1 .

A identificação de subdiretórios que não contêm o arquivo é respondida em outra pergunta

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

No entanto, se eu tentar incluir o grep no comando acima, ele não funciona

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

Como posso incluir a pesquisa de strings para me devolver o diretório de interesse?

    
por WanderingMind 23.09.2015 / 19:16

2 respostas

4

Você pode adaptar qualquer uma das soluções, por exemplo,

  • use ( -exec ou -exec ) com as soluções slm ou patrick (o segundo exec é executado somente se o primeiro retornar false , -print será executado somente se um deles retornar true ):

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

    ou ainda mais curto, como sugerido por Costas :

    find . -type d \! -exec grep -q 'str1' {}/stdout 2>/dev/null \; -print
    
  • use uma condição com a solução terdon :

    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
    
  • ou, com zsh :

    print -rl **/*(/e_'[[ ! -f $REPLY/stdout ]] || ! grep -q str1 $REPLY/stdout'_)
    
por 23.09.2015 / 20:28
2

Para obter essa lista, use apenas grep :

grep -L str1 dir-*/stdout

Onde:

  • -L fornece apenas o arquivo sem correspondência.
  • str1 é a string que você deseja pesquisar.
  • E se seus arquivos estiverem na mesma profundidade, você poderá usar curingas simples.
    • Se não, use o -r flag de grep para pesquisar de forma negativa nos diretórios.

Para continuar com isso e trabalhar nessa lista, você poderia canalizá-lo com delimitação de bytes nulos ( grep s -Z ) para um loop while:

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