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ãogrep ':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, grep
caso 1
nenhuma 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ágrep
trabalhar 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$f
começa com,./
portanto não pode começar com-
. - Eu usei
rm -i
apenas 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ídagrep
é maior que1
; você provavelmente não deseja remover o arquivo. Minha solução testa se o status de saída é exatamente1
.- 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 globstar
and**
) ou uma solução baseada emfind
será ú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