Elimine todos los archivos que NO contengan un patrón en el contenido

Elimine todos los archivos que NO contengan un patrón en el contenido

¿Cómo elimino todos los archivos que no contienen un texto específico?

Entiendo la solución para eliminar archivos con un texto específico, pero necesito eliminar archivos que NO contengan un patrón específico.

El siguiente comando crea una lista de archivos que no contienen "ejecución exitosa":

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

Deseo eliminar directamente estos archivos.

Respuesta1

Su enfoque original para identificar archivos apropiados

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

Es defectuoso. Preocupaciones principales:

  • ¿Qué pasa si hay dos o más líneas coincidentes en un archivo? grep ":0"parece ajustarse mejor a la condición del título de su pregunta ("archivos que no contienen un patrón").
  • ¿Qué pasa si :1(o :0) está en el nombre del archivo? Entonces grep ':0$'parece aún mejor.
  • ¿Qué pasa si hay un carácter de nueva línea en cualquier nombre de archivo pasado desde el primero grep?

Yo digo que no confíes en grep -c; confíe en el estado de salida grepsi 1no se seleccionaron líneas.

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

Notas:

  • [ -f "$f" ] && …no permitirá greptrabajar con directorios, fifos, etc. que coincidan *.out; sólo archivos normales.
  • --Se explica el significado y la importancia deaquí. Es en caso de que haya un archivo con un nombre que comience con -, se puede confundir con una opción. Otra forma de abordar este problema es for f in ./*.out; do …. De esta manera cada expandido $fcomienza con ./por lo que no puede comenzar con -.
  • Lo usé rm -ipor si acaso. Después de probar la solución, es posible que desee omitirla -i.
  • grep … || rm …es peor. Cuando ocurre un error real (por ejemplo, permiso denegado), el estado de salida de grepes mayor que 1; Probablemente no quieras eliminar el archivo entonces. Mi solución prueba si el estado de salida es exactamente 1.
  • Su código original no desciende a subdirectorios, ni el mío tampoco. Si desea recursividad, entonces será útil un shell que la admita (por ejemplo, Bash con shopt -s globstary **) o una solución basada en .find

Respuesta2

Teniendo en cuenta que sus archivos tienen una única "ejecución exitosa" o ninguna, entonces:

Para encontrar los archivos coincidentes, puede hacer:

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

para encontrarlos y eliminarlos:

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

para encontrar los archivos que no coinciden, haga lo siguiente:

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

para encontrarlos y eliminarlos:

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

Las banderas significan:

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

información relacionada