¿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? Entoncesgrep ':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 grep
si 1
no 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ágrep
trabajar 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 esfor f in ./*.out; do …
. De esta manera cada expandido$f
comienza con./
por lo que no puede comenzar con-
.- Lo usé
rm -i
por 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 degrep
es mayor que1
; Probablemente no quieras eliminar el archivo entonces. Mi solución prueba si el estado de salida es exactamente1
.- 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 globstar
y**
) 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