Codigo para eliminar archivos no existentes.

Iniciado por xgorum, 9 Julio 2016, 00:37 AM

0 Miembros y 1 Visitante están viendo este tema.

xgorum

Bueno antes que nada pido mil perdones pues solo me registe para pedir ayuda y como usuario de foros se que no es de buen gusto pero busque y busque en google y no encontré nada. Mi nombre es Manuel y soy de Sevilla.

Tengo un problema. Estoy liado configurando Hyperspin. Los archivos que se usan en general para cada juego son las ROMs, las Wheel, los videos, las artes... todos van en carpetas distintas pero tienen el mismo nombre, por ejemplo para Game Boy el juego mario bros: la roms se llama Mario Bros.zip,  el vídeo se llama Mario Bros.mp4, el artwork Mario Bros.png, os podéis hacer una idea.

El caso es que tengo muchos más archivos media (vídeos, imágenes) que Roms. Por ejemplo para MAME tengo todos los media existentes pero no todas las Roms por lo que me gustaría eliminar todo los medias sobrante.
Parece una tontería pero cuando tienes que eliminar cerca 5000 archivos y para saber cuales tiene que compararlos con las roms te puede llevar años.

Entonces mi duda es si existe algún programa para tal hecho o si no como podría hacer un bat (por ejemplo) que me hiciese tal cosa, no se algo como:

- genero una txt con las roms [dir/b>"lista de archivos.txt"](Ese me lo se XD)
- comparo los archivos con los medias
- borro (o muevo de sitio) los media que no figuran en el txt.

Vuelvo a pedir disculpas por mi ignorancia pues mis estudios son de electrónica y lo mas que di fue ensamblador para programar microprocesadores.

Un Saludo a todos y si escribo aquí es por que sé que es de los mejores foros de programación en castellano que conozco

Eleкtro

Hola

¿Loas archivos multimedia tienen el mismo nombre que las ROM?, por ejemplo: "juego.png" y "juego.zip". En ese caso puedo ayudarte, de lo contrario creo que no. Aclara ese punto por favor.

Saludos!








xgorum

Si. Así es. Las Roms, y cada media van en carpetas distintas. Pero cada juego tiene el mismo nombre. Por ejemplo el juego Daytona USA: La rom se llama daytona.zip, el video se llama daytona.flv y su imagen se llama daytona.png.

Eleкtro

#3
En Batch no sería nada productivo, resultaría algo lento y produciría un código muy sucio.

Por ese motivo aquí abajo te muestro una solución basada en .NET (en dos lenguajes diferentes, VB.NET y C#, produciendo un código idéntico. elige el que prefieras), solo debes especificar las rutas correspondientes en la variable romsPath y el array miscPaths, y llamar al método RomUtil.CleanRoms().

Debo aclararte que para utilizar el siguiente código primero debes compilarlo (no lo puedes ejecutar directamente haciendo click en Windows...), y para ello lo puedes hacer con Visual Studio.

Este código es reproducible en otros lenguajes como Python, Ruby, etc, en los cuales así mismo necesitarás descargar el intérprete. En VBS también es reproducible, lo comento por que no necesitarías descargar "accesorios" adicionales (imagínatelo como hacer click en un archivo .bat), pero VBS también es un lenguaje limitado y habría que darle algunas vueltas con las funciones relacionadas del FileSystem, resultaría en un código algo feo y yo simplemente he preferido no ponerme a escribir instrucciones de más en un lenguaje que está de menos, pudiendo llevar a cabo lo mismo en otro lenguaje superior.




C#:
Código (csharp) [Seleccionar]
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Vb = Microsoft.VisualBasic;

public sealed class RomUtil {

   public static readonly string romsPath = "C:\\...carpeta de las roms\\";
   public static readonly string[] miscPaths = {
   "C:\\...carpeta de las imágenes\\",
   "C:\\...carpeta de los videos\\",
   "etc..."
   };

   private RomUtil() {}

   public static void CleanRoms() {

       Func<FileInfo, FileInfo, bool> comparisonPredicate =
           (FileInfo a, FileInfo b) => {
               return Path.GetFileNameWithoutExtension(a.Name).Equals(Path.GetFileNameWithoutExtension(b.Name), StringComparison.OrdinalIgnoreCase);
           };

       IEnumerable<FileInfo> romFiles = new DirectoryInfo(romsPath).GetFiles(searchPattern: "*", searchOption: SearchOption.TopDirectoryOnly);

       List<FileInfo> miscFiles = new List<FileInfo>();
       foreach (string dirpath in miscPaths) {
           miscFiles.AddRange(new DirectoryInfo(dirpath).GetFiles(searchPattern: "*", searchOption: SearchOption.TopDirectoryOnly));
       }

       foreach (FileInfo miscFile in miscFiles) {
           bool isNotFound = (romFiles.FirstOrDefault((FileInfo f) => comparisonPredicate(f, miscFile)) == null);

           if ((isNotFound)) {
               // Enviar el archivo a la papelera de reciclaje:
               Vb.FileIO.FileSystem.DeleteFile(miscFile.FullName, Vb.FileIO.UIOption.OnlyErrorDialogs, Vb.FileIO.RecycleOption.SendToRecycleBin);

               // O eliminarlo permanentemente:
               // miscFile.Delete();
           }
       }

   }

}



VisualBasic.NET:
Código (vbnet) [Seleccionar]
Imports System;
Imports System.Collections.Generic;
Imports System.IO;
Imports System.Linq;
Imports Microsoft.VisualBasic

Public NotInheritable Class RomUtil

   Public Shared ReadOnly romsPath As String = "C:\...carpeta de las roms\"
   Public Shared ReadOnly miscPaths As String() = {
       "C:\...carpeta de las imágenes\",
       "C:\...carpeta de los videos\",
       "etc..."
   }

   Private Sub New()
   End Sub

   Public Shared Sub CleanRoms()

       Dim comparisonPredicate As Func(Of FileInfo, FileInfo, Boolean) =
           Function(ByVal a As FileInfo, ByVal b As FileInfo)
               Return Path.GetFileNameWithoutExtension(a.Name).Equals(Path.GetFileNameWithoutExtension(b.Name), StringComparison.OrdinalIgnoreCase)
           End Function

       Dim romFiles As IEnumerable(Of FileInfo) =
          New DirectoryInfo(romsPath).GetFiles("*", SearchOption.TopDirectoryOnly)

       Dim miscFiles As New List(Of FileInfo)
       For Each dirpath As String In miscPaths
           miscFiles.AddRange(New DirectoryInfo(dirpath).GetFiles("*", SearchOption.TopDirectoryOnly))
       Next

       For Each miscFile As FileInfo In miscFiles
           Dim isNotFound As Boolean =
               (romFiles.FirstOrDefault(Function(f As FileInfo) comparisonPredicate(f, miscFile)) Is Nothing)

           If (isNotFound) Then
               ' Enviar el archivo a la papelera de reciclaje:
               FileIO.FileSystem.DeleteFile(miscFile.FullName, FileIO.UIOption.OnlyErrorDialogs, FileIO.RecycleOption.SendToRecycleBin)

               ' O eliminarlo permanentemente:
               ' miscFile.Delete()
           End If
       Next

   End Sub

End Class


Saludos!








Eleкtro

#4
De todas formas te muestro un método de limpieza que escribí en Batch para las roms del MAME+ ...hace años ya, exactamente para el mismo propósito que comentas, yo me descargaba "packs" de carátulas y demás, y claro, me sobraban la mitad de archivos por que yo no tenía todas las roms que hacian referencia a esas carátulas, como te pasa a ti.

Código (dos) [Seleccionar]
:Clean
FOR /F "Tokens=*" %%a in ('Dir /B /A ".\%~1" ^| Find /V /I "Default.cfg" ^| Find /V /I "output.xml"') do (
Set "Rom=%%a"
IF NOT exist ".\Roms\!Rom:~0,-4!.zip" (
IF NOT exist ".\Roms\!Rom:~0,-4!" (
Echo: %%a
MKDir ".\_Eliminados\%~1" 2>NUL
Move /Y "%~1\%%a" ".\_Eliminados\%~1\" >NUL
)
)
)
Echo+
Goto :EOF


Al código lo llamarías de la siguiente manera:

Código (dos) [Seleccionar]
@Echo OFF & Setlocal EnableDelayedExpansion
Call :Clean "C:\Carpeta de las imágenes"
Call :Clean "C:\Carpeta de videos"
...


Ten en cuenta que ese código asume que existe una carpeta llamada "Roms" en el directorio de trabajo.
Úsalo bajo tu responsabilidad.

Aquí publiqué el código entero:

Citar  

PD1: Las capturas las acabo de hacer, se ven con "malos" caracteres por la codificación actual que uso en la CMD en Windows 10.

PD2: Lo que puse de "Default.cfg" y "output.xml" en el código de arriba, si no recuerdo mal es por que son archivos que se deben ignorar, quiero decir, que no se deberían borrar en los directorios del MAME, pero hace mucho tiempo que no uso el MAME así que no te sabría confirmarlo ahora mismo. En el código de C# y VB.NET no se ignora ningún archivo, así que ten cuidado y haz una copia de seguridad antes de probar, si necesitas ignorar el "Default.cfg" y "output.xml" sería facil hacerlo.

Saludos








xgorum

Muchas gracias Elektro.
Esta noche en el curro me pondré a compilar y mañana lo pruebo en mi PC. Os mantendré informado de como funciona. Gracias de veras me ahorras muchas horas de trabajo.

dato000

Ay sensei en serio quedo ANOnadado de ver con cuanta maestria y sabiduria haces estas cosas...pero eliminar archivos???

naaa esos archivos del mame ni que llenaran el disco, y no tomaria años, ni siquiera días, solo una o dos horas máximo.

jajaj igual quede descrestado al ver ese programa, y con interfaz bonita y todo, y yo que todavia sigo tratando de entender Razor y MVC en Visual Studio, me hace sentir pequeño, pero motivado  :laugh: :laugh: