Remova todos os arquivos que NÃO contêm um padrão no conteúdo

Remova todos os arquivos que NÃO contêm um padrão no conteúdo

Como faço para remover todos os arquivos que não contêm um texto especificado.

Entendo a solução para remover arquivos com um texto especificado, mas preciso remover arquivos que NÃO contenham um padrão especificado.

O comando a seguir cria uma lista de arquivos que não contém "execução bem-sucedida":

grep -c "successful run" *.out | grep -v ":1" > err.txt

Desejo excluir diretamente esses arquivos.

Responder1

Sua abordagem original para identificar arquivos apropriados

grep -c "successful run" *.out | grep -v ":1"

É falho. Principais preocupações:

  • E se houver duas ou mais linhas correspondentes em um arquivo? grep ":0"parece se adequar melhor à condição do título da sua pergunta ("arquivos que não contêm um padrão").
  • E se :1(ou :0) estiver no nome do arquivo? Então grep ':0$'parece ainda melhor.
  • E se houver um caractere de nova linha em qualquer nome de arquivo passado desde o primeiro grep?

Eu digo para não confiar grep -c; depende do status de saída, grepcaso 1nenhuma linha tenha sido selecionada.

for f in *.out; do
   [ -f "$f" ] && {
      grep -q -- "successful run" "$f"
      [ "$?" -eq 1 ] && rm -i -- "$f"
   }
done

Notas:

  • [ -f "$f" ] && …não permitirá greptrabalhar com diretórios, fifos etc. que correspondam a *.out; apenas arquivos regulares.
  • O significado e significado de --é explicadoaqui. Caso exista um arquivo com nome começando com -, ele pode ser confundido com uma opção. Outra maneira de lidar com esse problema é for f in ./*.out; do …. Dessa forma, todo expandido $fcomeça com, ./portanto não pode começar com -.
  • Eu usei rm -iapenas no caso. Depois de testar a solução, você pode omitir -i.
  • grep … || rm …é pior. Quando ocorre um erro real (por exemplo, permissão negada), o status de saída grepé maior que 1; você provavelmente não deseja remover o arquivo. Minha solução testa se o status de saída é exatamente 1.
  • Seu código original não desce para subdiretórios, nem o meu. Se você deseja recursão, um shell que a suporte (por exemplo, Bash com shopt -s globstarand **) ou uma solução baseada em findserá útil.

Responder2

Considerando que seus arquivos têm uma única "execução bem-sucedida" ou nenhuma, então:

para encontrar os arquivos correspondentes, você pode fazer:

grep -l "successful run" *.out > err.txt

para localizá-los e removê-los:

grep -l "successful run" *.out | xargs rm

para encontrar os arquivos sem correspondência, faça:

grep -vl "successful run" *.out > ok.txt

para localizá-los e removê-los:

grep -vl "successful run" *.out | xargs rm

As bandeiras significam:

-l lists the files with matches
-v/--invert-match inverts the matching logic

informação relacionada