
Me gustaría eliminar todos los archivos txt, xls, pdf de un directorio, así como sus subdirectorios. Me gustaría guardar todo lo demás.
find . -type f ! -iname '*.xml$,.png$,.jpeg$,.gif$,' -delete
Eso parecía haberlo hecho, pero elimina algunos otros archivos que necesito. ¿Cómo puedo lograr eso sin eliminar nada más?
Respuesta1
Haz esto en su lugar:
find . -type f -iname '*.xml' -o -iname '*.png'\
-o -iname '*.jpeg' -o -iname '*.gif' -delete
También puedes usar expresiones regulares:
find . -type f -iregex '.*\.\(xml\|png\|jpeg\|gif\)$' -delete
Respuesta2
Básicamente, existen 4 formas de abordar este problema utilizando find.
Método n.° 1: usar-delete
$ find . -type f -iname '*.xml' -o -iname '*.png'\
-o -iname '*.jpeg' -o -iname '*.gif' -delete
Como otros han mencionado en estas preguntas y respuestas, este método es el más rápido y el que requiere menos recursos. Citando delbuscar documentos en línea:
10.1.6 Usando la acción `-delete'
El método más eficiente y seguro para resolver este problema es utilizar la acción "-delete":
find /var/tmp/stuff -mtime +90 -delete
Esta alternativa es más eficiente que cualquiera de las
-exec' or
acciones -execdir', ya que evita por completo la sobrecarga de bifurcar un nuevo proceso y usarexec' to run
/bin/rm'. Normalmente también es más eficiente quexargs' for the same reason. The file deletion is performed from the directory containing the entry to be deleted, so the
la acción -delete. Tiene las mismas ventajas de seguridad que la acción "-execdir".La acción "-delete" fue introducida por la familia de sistemas operativos BSD.
NOTA:Una cosa a tener en cuenta con este enfoque es que el uso de -delete
implica también el cambio -depth
. ¿Qué quiere decir esto? Aquí tienes un ejemplo de cómo -delete
puedes quemarte si no tienes cuidado.
Por ejemplo, digamos que tengo un directorio de trabajo de subversion donde quiero limpiar algunos archivos, pero dejo intactos sus subdirectorios .svn. Podría usar el siguiente comando para lograr esto:
$ find . -not "(" -name .svn -type d -prune ")" -type f -print
./a.txt
Pero debido a que -delete
incluye un -depth
modificador, los archivos que realmente se tratarían:
$ find . -not "(" -name .svn -type d -prune ")" -type f -print -depth
./.svn/all-wcprops
./.svn/entries
./.svn/format
./.svn/text-base/a.txt.svn-base
./a.txt
Por este motivo, a la hora de utilizarlo -delete
hay que tener cuidado.
Método #2 --exec command {} +
$ find . -type f -iname '*.xml' -o -iname '*.png'\
-o -iname '*.jpeg' -o -iname '*.gif' -exec rm {} \+
En comparación con el -delete
método, esta es probablemente la siguiente mejor opción, en términos de rendimiento y portabilidad en Unix. La -exec ... {} +
notación funciona de la siguiente manera:
desde la página de manual de búsqueda
Esta variante de la acción -exec ejecuta el comando especificado en los archivos seleccionados, pero la línea de comando se crea agregando cada nombre de archivo seleccionado al final; el número total de invocaciones del comando será mucho menor que el número de archivos coincidentes. La línea de comando está construida de manera muy similar a como xargs construye sus líneas de comando. Sólo se permite una instancia de `{}' dentro del comando. El comando se ejecuta en el directorio de inicio.
Entonces, en efecto, este método funciona de manera similar a xargs
, pero sin tener que pasar por el aro de pasar la salida de un hallazgo a través de una tubería a xargs
.
Método #3 -xargs
$ find . -type f -iname '*.xml' -o -iname '*.png'\
-o -iname '*.jpeg' -o -iname '*.gif' -print0 | xargs -0 rm -f
Creará find ... -print0
una lista de archivos que coincidan con los criterios especificados. Luego, esta lista se pasa a través de la tubería a xargs
. El -print0
interruptor coloca un carácter ASCII NUL como separador entre cada resultado de la búsqueda. El -0
encendido xargs
hace que se asuma que los archivos que se pasan están separados por caracteres ASCII NUL.
En comparación con los métodos n.° 1 y n.° 2, este tendrá un rendimiento similar al n.° 2; sin embargo, el -print0
conmutador no es compatible universalmente en todos los Unix.
Método #4 --exec command {} \;
$ find . -type f -iname '*.xml' -o -iname '*.png'\
-o -iname '*.jpeg' -o -iname '*.gif' | exec rm -f {} \;
En comparación con los primeros 3 métodos, este es el de menor rendimiento. Literalmente llama al rm
comando para cada archivo individual que find
encuentra el comando.
Consideraciones adicionales sobre la seguridad
Una cosa que puede no ser tan obvia al utilizar cualquiera de los métodos anteriores es que algunos de ellos son más seguros que otros. Probablemente te estés diciendo a ti mismo... ¿seguridad? .. ¿qué? He aquí un ejemplo.
Asume tu root y ejecuta el siguiente comando:
$ find /var/tmp/somedir -type f -exec rm {} \;
Sin que usted lo sepa, alguien ha creado maliciosamente un enlace al /etc
directorio en /var/tmp/somedir
. Cuando se ejecute el comando anterior, el /etc
directorio también se eliminará. Este problema existe con cualquiera de los métodos para eliminar archivos, excepto con la -delete
opción (método n.° 1).
tl;dr;
La forma más rápida y segura de eliminar archivos con la ayuda de buscar es utilizar -delete
. El uso xargs -0
puede tener un rendimiento similar, pero no es tan seguro. La -delete
acción no es completamente portátil. La alternativa portátil más eficiente es -exec ... +
, pero es insegura y no es compatible con versiones de GNU findutils anteriores a la 4.2.12.
Referencias
Respuesta3
Hay una ligera inexactitud enrespuesta slm.
NOTA y descargo de responsabilidad: esto tiene que ser un comentario pararespuesta slmpero ahora mismo no puedo hacer comentarios todavía.
El ejemplo "alguien ha creado un enlace maliciosamente" dado enConsideraciones adicionales sobre la seguridadno es totalmente exacto tanto sobre los enlaces físicos de Unix como sobre los enlaces blandos de Unix.
Para comprender la diferencia entre los dos, consulteEnlace físico y enlaces simbólicos en Unixo búscalo en Google.
Para enlaces blandos (el tipo más utilizado de todos modos) tanto GNU find
comoBDS find
no essiga enlaces simbólicos a menos que se utilice una -L
bandera específica para forzar el seguimiento de enlaces simbólicos. [Ver man find
]
Por lo tanto, es probable que este ejemplo no sea un problema, a menos quefuerza find
para seguir enlaces suaves usando la -L
bandera. De todos modos, esta es la elección peligrosa.
Para enlaces físicos, find
siga el enlace aotro archivopero tenga en cuenta que el enlace físico a unotro directorio"probablemente fallará" como se ve man ln
en GNU ln
:
-d, -F, --directory
allow the superuser to attempt to hard link directories (note: will probably
fail due to system restrictions, even for the superuser)
Por lo tanto, en primer lugar, probablemente sea imposible crear el enlace físico a un directorio y find
no tendrá nada que seguir.
Tenga en cuenta que algunas ln
implementaciones de BDS no tienen ninguna -d
opción.