![Eliminar archivos con contenido específico](https://rvso.com/image/178487/Eliminar%20archivos%20con%20contenido%20espec%C3%ADfico.png)
Teniendo miles de archivos de datos (misma extensión) en un directorio, ¿cómo eliminar aquellos que contienen una declaración de parámetro específica?
Por ejemplo, si eliminara todos los archivos que contienen la línea
Key = 0
¿podría hacer algo como
grep -i "Key = 0" * | rm *
Respuesta1
Puede utilizar el siguiente comando en el shell. Esto debería funcionar si el patrón a buscar esKey = 0
grep -lrIZ "Key = 0" . | xargs -0 rm -f --
Comando genérico:
grep -lrIZ "<Pattern to be searched in the file>" . | xargs -0 rm -f --
Respuesta2
El principal problema con la tubería que usa grep
+ rm
es que rm
no lee su flujo de entrada estándar, lo que significa que no lee nada del grep
comando en el lado izquierdo de la tubería.
En cambio, rm *
en el lado derecho de la tubería ignoraría todas las entradas y ejecutaría rm
en cada nombre de archivo visible en el directorio actual.
Ignorando el problema de rm
no leer su entrada estándar, su grep
comando tiene dos problemas principales:
- Genera líneas coincidentes con nombres de archivos. Esto no serviría de nada
rm
como necesitamos saber.sololos nombres de los archivos que queremos eliminar. - Coincide
Key = 0
como unsubcadena, lo que significa que también coincideCrypto Key = 0x01
, etc.
find . -type f -exec grep -q -F -x 'Key = 0' {} \; -exec rm -f {} +
o, con GNU find
(y algunos otros),
find . -type f -exec grep -q -F -x 'Key = 0' {} \; -delete
Ambos buscarían archivos normales en el directorio actual o debajo, y para cada archivo encontrado, ejecutarían grep -q -F -x 'Key = 0'
. Este grep
comando devolvería un estado de salida que indica si hay una línea en el archivo que estáexactamente Key = 0
(y nada más).
El segundo find
comando eliminará el archivo usando su -delete
predicado si se encuentra dicha línea. El primer find
comando recopilaría los nombres de ruta de los archivos que contienen esta línea y luego se ejecutaría rm -f
en lotes de estos.
Las banderas utilizadas grep
son
-q
, para un funcionamiento silencioso. La utilidad no genera líneas coincidentes, pero sale exitosamente después de la primera coincidencia o con un estado de salida distinto de cero si el archivo no contiene una coincidencia.-F
, para una coincidencia de cadenas fija. Estamos haciendo coincidir con una cadena, no con una expresión regular.-x
, para buscar solo coincidencias completas. Esto tiene el mismo efecto que si usara una expresión regular anclada tanto al inicio como al final de la línea.
No estoy usando -i
aquí grep
porque eso también eliminaría archivos que contienen líneas como KEY = 0
y kEY = 0
etc., y no has dicho nada sobre estas variaciones de casos.
¿Desea que el find
comando se restrinja a un sufijo de nombre de archivo particular, como .ext
, y luego utilícelo -name '*.ext'
en el find
comando antes de la ejecución de grep
. Por ejemplo:
find . -name '*.ext' -type f -exec grep -q -F -x 'Key = 0' {} \; -exec rm -f {} +