Usando find para encontrar archivos

29 12 2008

Bien, muchos de los que leen seguramente se habran encontrado con comandos en internet que lucen asi:

carlos@carlos-laptop:~$ find Music/ -type f -exec chmod -x '{}' \;

Criptico ? Bien, mas nunca. Hace mas de una semana tengo el libro “La biblia de Unix” de Dave Taylor, muy buen libro la verdad, uno se entera de muchisimas cosas. Una de ellas es como usar find y otra sobre la que probablemente escribire mas tarde es como usar vi. Pero centremonos en find…

Por muy organizado que tengamos nuestro arbol de directorios en algun momento nos hallaremos en necesida de buscar un archivo de cuya ubicacion no nos acordemos, o quizas buscamos algun archivo de configuracion en / o quiza otra cosa. Para eso esta find. Veamos un ejemplo sencillo, encontrar el archivo tarea_de_quimica.odt en $HOME:

$ find $HOME -name tarea_de_quimica.odt

Bien, pronto (si tenemos el archivo) nos dira la ruta completa del archivo, util eh? Probablemente ya hayan notado la sintaxis del comando

find ruta_de_busqueda opciones

Las opciones mas resaltantes, o bien, las que mas uso son:

Opcion Significado
-name nombre Busca un archivo con el nombre que demos
-iname Lo mismo de arriba pero no le importan mayusculas o minusculas
-ctime n El archivo fue creado hace n dias
-cmin n El archivo fue creado hace n minutos
-type Busca archivos de un tipo especificado, b (block especial) , c ( character especial), d (directorio) , p ( named pipe ), f (archivo normal), l ( enlace simbolico), s (socket), D (door –solaris* )
-amin n El archivo fue accedido hace n minutos
-atime n Verdadero si el archivo se accedio hace n dias (Les recomiendo leer lo que dice man sobre esta opcion)
-empty El archivo esta vacio
-fstype type El archivo esta en una particion del tipo type (vfat, ext3, etc)
-group grupo El archivo le pertenece a el grupo grupo
-regex Buscar con expresiones regulares
-mmin n El archivo fue modificado hace n minutos
-mtime n El archivo fue modificado hace n horas
-perm mode El archivo tiene ciertos permisos
-size n[cwbkMG] El archivo usa n unidades de espacio, los sufijos uados pueden ser b para bloques de 512-byte), c para bytes, w para two-byte words, k para kb, M para mb y G para GB.
-user nombre El archivo pertenece a un usuario (nombre)

Para las opciones que tienen que ver con el tiempo se puede usar el prefijo + (X tiempo o mas) y – (X tiempo o menos).

Faltaron, como es habitual algunas opciones, pero creo que este es un buen recaudo de ellas. Muchas de ellas variantes de -perm y algunas com -wholename que pueden ser consultadas con
$ man find
Ahora, esta es la parte de los ejemplos.
Buscar un archivo con el nombre de InStRuMeNtOsDeLaBoRaToRiO.odt en $HOME/Documentos/:
$ find $HOME/Documentos/ -iname instrumentosdelaboratorio.odt
Buscar un archivo que recordamos que contenia la palabra Stephen (En home):
$ find $HOME -iregex .*Stephen.*
Buscar un archivo que sabemos fue accedido hace 10 minutos:
$ find $HOME -amin 10
Buscar un archivo que pudo haber sido accedido hace 10 minutos o menos:
$ find $HOME -amin -10 #El archivo fue accedido hace 2 minutos ( eso no lo dice el programa )
Buscar un archivo que tiene permisos ejecutables en /home:
$ find /home -perm -aug=x #solo es a (todos) u (usuario) o g (grupo) no las tres combinadas
Buscar archivos vacios en nuestro directorio
$ find $HOME -empty #Esto busca tanto archivos como carpetas
Especialicemos un poco la busqueda anterior y centremonos en archivos
$ find $HOME -empty -type f
Eso muestra como se pueden combinar varias opciones, siempre y cuando sea una combinacion con logica ;)
Ahora vamos a hacer algo de verdad util, busquemos archivos en el sistema que excedan los 4GB y que sean archivos normales, ademas de haber sido modificados recientemente (Estamos buscando peliculas :) :
$ find /home -type f -mtime -5 -iname *.iso -size +4G
Esto buscara todos los arhivos .iso creados hace 5 dias o menos. (es decir, 2, 3, 4 dias).

Bien, ya sabemos como buscar, pero que pasaria si queremos hacerle algo a los archivos que encontremos, cambiarles los permisos, borrarlos, cambiarles el nombre, etc. Sencillo, usemos la opcion -exec, asi

$ find busqueda -exec acciones \;

Ejemplo, copiamos musica de un pendrive a nuestra carpeta de musica, pero esta musica se paso con +x en los permisos (ejecutable), nosotros queremos cambiar eso, pero hay unos 1000 archivos mas en la carpeta, incluyendo muchos directorios…. y ahora?

$ find Music/ -type f -cmin -5 -iname *.ogg -exec chmod -x '{}' \;
Ahora, por orden, primero le decimos que busque archivos normales (no directorios), despues que fueron creados hace al menos 5 minutos, por ultimo le damos la extension (en este caso ogg, si copiamos de diferentes formatos pueden quitar esta parte), por ultimo damos -exec y ponemos la orden que se debe ejecutar con estos archivos, chmod -x (quitar permiso de ejecutar) a ‘{}’ (que representa el archivo que ha encontrado find ).

Entonces, resumiendo esto, ‘{}’ es un comodin al nombre del archivo actual que ha encontrado find. Por ejemplo, find encuentra a1, a2, a3. Primero se va a procesar a1 con la instruccion, despues a2 y asi sucesivamente.

Bien, vamos a hacer una pequena seccion de “aplicando lo aprendido para crear un script”. Este script es muy util, muy pero muy util y te deja mucho tiempo libre.

Primero creemos un directorio llamado bin en tu home

$ mkdir $HOME/bin

Ahora, si es necesario editemos .profile para anadir $HOME/bin a nuestro $PATH. Nos desplazamos al directorio creado y creamos un archivo llamado create-db con lo siguiente

#!/bin/bash
find / -print < $HOME/db

Este sencillo script crea una “base de datos” en un archivo con todos los archivos de tu sistema. Esto tarda un poquito porque escanea todo tu sistema de archivos. Le damos permisos de ejecucion
$ chmod +x create-db
Y lo corremos
$ ./create-db
Ahora Creemos otro archivo que se llame find-in-db con lo siguiente

#!/bin/sh
if [ $# -eq 0 ]; then
	echo "Usage: find-in-db file"
	exit 1
fi
egrep -i "$@" $HOME/db

Tambien le damos permisos de ejecucion… Ok, ahora vamos a usarlo para buscar todos los .ogg de nuestro sistema:

$ ./find-in-db *.ogg
Ante nuestros ojos, y en practicamente un segundo esta la lista completa de todos los ogg de nuestro equipo, sin tener que recorrerlo todo hemos encontrado los archivos! Este scrpit lo podemos ampliar/especializar para que busque todos los archivos multimedia de nuestro home:

#!/bin/bash
find $HOME -regex ".*\.m[p4].?\|.*\.og.?\|.*\.aac\|.*\.w[am].?" -print < $HOME/music-db

(Este es otro creador de bases de datos)
A este le podemos hacer su script para busqueda (igual al otro, pero grep busca $HOME/music-db)… Este es uno de los muchos usos de find/grep (tratare de hablar de este ultimo despues).

Espero que les haya resultado util, saludos :P


Acciones

Información

Deja un comentario