Buscar este blog

martes, 1 de diciembre de 2009

Archivado de carpetas obsoletas.

Pongamos que eres un administrador de sistemas, y una de tus responsabilidades es administrar el servidor de ficheros de tu empresa. Pongamos también que en ese servidor de ficheros, tienes una carpeta que se llama, por ejemplo, proyectos, donde se han ido almacenando en carpetas individuales los proyectos que tu empresa ha ido realizando desde que a alguien se le ocurrió hacerlo. Supongamos que nadie, nunca, se ha molestado en archivar las carpetas de los proyectos que iban finalizando. Y supongamos por último, que el volumen de información ha ido creciendo hasta alcanzar el máximo de tamaño que tu pequeña SAN permite (2TB). En ese preciso instante te despiertas empapado en sudor pensando que todo ha sido un mal sueño. Pero a veces, solo a veces, algunos sueños pueden hacerse realidad.

El tema del archivado de información obsoleta es algo que me preocupa hace tiempo, aunque hasta ahora no he tenido tiempo de poder analizar en profundidad el problema. La principal barrera que siempre nos ha impedido realizar un archivado tradicional en cinta, es que el sistema que se utiliza para archivar en cinta, no archiva estructuras completas de carpetas, sino que analiza cada archivo y carpeta de forma individual y lo compara con el patrón de archivado que hayas definido (por fecha de modificación, de acceso, etc.). Desgraciadamente para mi, nosotros no podemos archivar de esa forma, ya que necesitamos que cuando se archiva un proyecto se archive toda la información relativa a ese proyecto de forma consistente. La gente de Microsoft ha hecho un gran trabajo al incluir de forma nativa en Windows 2008 R2 herramientas de archivado que facilitan mucho la vida del administrador, pero desgraciadamente (¿porque en informática siempre hay un desgraciadamente detrás de cada esquina?), estas herramientas no son demasiado aplicables a información obsoleta, además, habría que migrar el servidor de ficheros a Windows 2008 R2, con todo lo que ello implica.

En fin, la pregunta es: ¿Hay alguna solución para archivar carpetas completas basándonos en la última fecha de acceso? Mi aproximación al problema, como hago normalmente cuando algo se complica, es programar algo específico. En este caso, el script que he preparado comprueba todos los archivos que hay dentro de las carpetas de una ruta dada (nuestra inquietante carpeta de proyectos) e imprime el nombre de la carpeta, la ruta UNC a la carpeta y la fecha del acceso más reciente a cualquiera de los archivos contenidos en ella. El script en sí, es una modificación de un script posteado en el blog de Hey, scripting Guy! El código del script es el siguiente:

Set objFSO = CreateObject("Scripting.FileSystemObject")
objStartFolder = "C:\Scripts"

Set objFolder = objFSO.GetFolder(objStartFolder)
Wscript.Echo objFolder.Path
Set colFiles = objFolder.Files
For Each objFile in colFiles
Wscript.Echo objFile.Name
Next
Wscript.Echo

ShowSubfolders objFSO.GetFolder(objStartFolder)

Sub ShowSubFolders(Folder)
For Each Subfolder in Folder.SubFolders
Wscript.Echo Subfolder.Path
Set objFolder = objFSO.GetFolder(Subfolder.Path)
Set colFiles = objFolder.Files
For Each objFile in colFiles
Wscript.Echo objFile.Name
Next
Wscript.Echo
ShowSubFolders Subfolder
Next
End Sub


Como podéis ver, el script realiza las siguientes acciones:
•Crea un objeto FSO para trabajar con ficheros locales
•Define en una variable la carpeta que se va a examinar
•Enlaza el objeto FSO creado a la carpeta que se ha definido en la variable
•Muestra la ruta de acceso de la carpeta (como se explica en el enlace, esta ruta puede ser local, o una ruta UNC usando carpetas compartidas).
•Se introducen los ficheros que hay dentro de la carpeta en una colección para poder acceder a las propiedades de cada fichero individualmente.
•Se muestra el nombre de cada fichero
•Se llama a una función (Sub) la cual hace lo mismo que hemos comentado antes por cada subcarpeta de forma anidada. Es decir, en cada subcarpeta, la función se llama a si misma hasta que se llegue a una subcarpeta en la que no haya más carpetas.

Este script, está muy bien, pero aun así, no nos sirve para lo que nosotros queremos exactamente, por lo que le añadimos algunas líneas de código más:

On Error Resume next
Set objFSO = CreateObject("Scripting.FileSystemObject")
objStartFolder = “\\Ruta_UNC\carpeta”

fecha2 = CDate("30/11/1990 22:20:59")

ShowSubfolders objFSO.GetFolder(objStartFolder), 1, fecha2

Sub ShowSubFolders(Folder, level, fecha2)
On Error Resume next
For Each Subfolder in Folder.SubFolders
If level = 1 Then
Wscript.StdOut.write Subfolder.name & ";" & Subfolder.Path
End if
Set objFolder = objFSO.GetFolder(Subfolder.Path)
Set colFiles = objFolder.Files
For Each objFile in colFiles
If fecha <>
fecha = objFile.DateLastAccessed
End if
Next
If Err.Number <> 0 Then
fecha = Now()
Err.clear
End If
ShowSubFolders Subfolder, level + 1, fecha2
If level = 1 Then
WScript.StdOut.writeline ";" & fecha
fecha = fecha2
End If
Next
End Sub

Como podéis ver, he añadido un par de opciones:
•En primer lugar, elimino el recorrido inicial que se ha ce por la carpeta raíz, ya que ese dato no me interesa.
•Inicializo una variable de fecha, que se mantendrá constante. Se inicializa a una fecha suficientemente antigua, y para darle formato de tipo date a la variable, usamos la función CDate, que convierte la cadena de fecha al tipo de variable fecha. De este modo podemos inicializar las variables a la fecha que queramos.
•Llamamos a la función de mostrar subcarpetas y a parte del objeto folder que contiene la carpeta raíz con la que trabajamos, le pasamos 2 variables mas. La primera (pasando un uno) nos dirá el nivel de la subcarpeta con respecto a la ruta UNc que hemos definido inicialmente, lo que nos permitirá después filtrar los resultados mostrados para escribir la fecha solo en las carpetas del primer nivel y reinicializar la variable fecha a fecha2. La segunda variable es la variable Fecha2, que es constante y que hemos inicializado anteriormente a una fecha suficientemente antigua.
•Al principio de la función, comprobamos que la carpeta que estamos trabajando es de nivel 1 e imprimimos su nombre y su ruta, separados por ;
•Comprobamos fichero por fichero de cada subcarpeta que la variable fecha es mas reciente que la fecha de ultimo acceso del fichero. Si no lo es, asignamos a la variable fecha la fecha de último acceso de ese fichero. De ese modo, la variable fecha, va almacenando la fecha de acceso más reciente de cualquiera de los ficheros de la subcarpeta.
•Cuando volcamos la lista de ficheros, añadimos un if con control de errores por si hay un error (no tener acceso a la carpeta es el más común), y reseteamos la fecha de acceso al día de hoy.
•Por último, después de llamar otra vez a la función de mostrar subcarpetas, comprobamos que la carpeta con la que trabajamos es de nivel 1 y si lo es, escribimos la fecha y la reinicializamos.

Con este script obtendréis una salida de texto separado por ; que podéis exportar fácilmente a Excel y filtrar de la forma que mas os convenga. Para ello, recordad que tenéis que usar la redirección de salida desde una línea de comandos, algo así:

cscript c:\miscript > c:\salida_script.txt

Saludos a todos.