Pregunta Cómo combinar carpetas duplicadas con la estructura "name (1)", "name (1) (1)" etc.


Al sincronizar mi Google Filestream, Google Drive y Synology CloudSync, todo se arruinó y me quedan cientos de carpetas duplicadas con el nombre de la carpeta seguido de un "(1)" o "(2)", etc. hasta "(1) (1) (1)".

¿Conoces un programa o script que pueda fusionar estas carpetas?

Ejemplo de estructura de carpetas de nivel superior:

1100 Beetledwarf - Happy ATE
1100 Beetledwarf - Happy ATE (1)
1100 Beetledwarf - Happy ATE (2)
1100 Beetledwarf - Happy ATE (3)
1100 Beetledwarf - Happy ATE (3) (1)
1100 Beetledwarf - Happy ATE (3) (1) (1)
1100 Beetledwarf - Happy ATE (4)
1100 Beetledwarf - Happy ATE (5)
1100 Beetledwarf - Happy ATE (6)

Debido a que las subcarpetas a veces también tienen el mismo problema, el programa o script necesitaría poder fusionar las carpetas que siguen ese patrón de nomenclatura para todas las subcarpetas, por ejemplo:

Ejemplo de carpetas de segundo nivel:

1100 Beetledwarf - Happy ATE (6)
    Analysis
    Analysis (1)
    Smirckle_HL
    Smirckle_HL (2)
    Pending Reports
    Photos & Logos

La mejor solución también me permite mover archivos en lugar de copiarlos, ya que lleva mucho tiempo copiar archivos, pero moverlos es casi instantáneo.

Lista de cosas que ya he probado, pero ninguna de ellas puede tratar con la estructura de carpetas "name (1)" (que puedo decir hasta ahora), y todas ellas copian archivos en lugar de moverlos:

  • WinMerge para Windows 10 <- se atraganta al intentar copiar los archivos de la unidad de Google (devuelve algo como "comando de DOS no compatible" para ellos)
  • Meld para MacOS. <- lento.
  • Terminal con comando "ídem" en OS X <- La mejor opción hasta el momento.

¡Gracias por tu ayuda!


1


origen


Si lo entendí correctamente, mover los archivos en su caso a través de la conexión a Internet tomará el mismo tiempo que los copió. Lo confunde con archivos en movimiento, por ejemplo dentro una partición HD, eso es rápido. Moverlos entre particiones, entre discos duros, entre PC, etc., generalmente llevará mucho más tiempo (sin considerar la excepción con ciertas configuraciones). - Albin
Gracias, eliminé el bit sobre mi conexión a Internet porque es extraño. Al usar la secuencia de archivos google en Windows y Mac OS, si mueve archivos, es como mover archivos dentro de una partición HD: si mueve archivos, el sistema operativo generalmente solo cambia los punteros que apuntan al archivo, pero si los copia, entonces el sistema operativo generalmente copia los datos a una nueva ubicación en el disco. En este caso, la copia tarda aún más tiempo porque el HD está conectado a través de Internet. ¡Aclamaciones! - Josh
Hola. Estoy trabajando en un script pyhton para resolver específicamente tu pregunta. Está razonablemente preparado, pero desafortunadamente no puedo pasar más tiempo realizando los (importantes) toques finales (salvaguardas) hasta el lunes, = / ya que estaré viajando. Si te tropiezas con una respuesta antes de eso, bueno, genial para ti de todos modos = D, pero si no encuentras ninguna, puedo terminarla y publicarla aquí como respuesta =). Tenga un buen día. - Vinícius M


Respuestas:


Este es el enfoque que probaría en Linux. No tengo experiencia con Google Filestream, Google Drive ni Synology CloudSync, por lo que no puedo decir si la solución se puede aplicar en absoluto. Todavía espero que esto al menos te dé algunas ideas.


Suposiciones

  • puedes montar el recurso compartido en tu árbol de directorio, por lo mv, cp y otras herramientas sensatas pueden funcionar con directorios como si fueran locales;
  • archivos (o directorios) con rutas que se vuelven idénticas después de eliminar todas (N) las cadenas son, de hecho, instancias del mismo archivo (directorio);
  • las instancias del mismo archivo deben dejar solo un archivo;
  • las instancias del mismo directorio deberían fusionar su contenido en un solo directorio;
  • puedes usar todas las herramientas que uso aquí.

Procedimiento

Lea la respuesta completa antes de intentar hacer algo.

Creo que algunos pasos podrían escribirse como un script, pero dado que la solución es altamente experimental, es mejor hacerlo a mano, paso a paso, prestando atención a lo que sucede.

  1. En un caparazón cd al punto de montaje e invocar find . | vidir -; use un editor de texto de su elección, p. kate, Me gusta esto:

    find . | EDITOR=kate vidir
    

    Esto abrirá el editor con una lista de todos los objetos, cada uno con su propio número al frente. Cuando modifica el contenido y guarda el archivo (temporal) y cierra el editor, se aplican todos los cambios. En general, esto es lo que puedes hacer:

    • cambiar las rutas para mover (renombrar) archivos o directorios;
    • eliminar líneas para eliminar archivos o directorios;
    • intercambia dos o más números para intercambiar archivos (no lo necesitarás).

    No guarde el archivo a menos que esté seguro de que el nuevo contenido describe el árbol de directorios que desea obtener.

  2. Copie el contenido del editor a otro archivo. El punto es trabajar con él y pegar el resultado (y guardarlo) solo cuando esté seguro de que lo hizo bien. Los siguientes pasos se refieren al nuevo archivo a menos que se indique explícitamente lo contrario.

  3. Utilizar sed o cualquier otra herramienta para deshacerse de todos (N) cadenas (tenga en cuenta el espacio principal). En este punto, debe obtener rutas "limpias", muchas de ellas ocurrirán más de una vez (con diferentes números dados por vidir)

  4. Utilizar sort -k 2 ordenar de acuerdo a estos caminos. Gracias a -s el ex Analysis todavía debe preceder a la anterior Analysis (1).

  5. Utilizar uniq -f 1 para dejar rutas duplicadas. Ahora cualquier camino debería ocurrir solo una vez.

  6. Comprueba dos veces la cordura de la estructura de directorios codificada en el resultado.

  7. Pegue el resultado en el editor original, guarde el archivo y salga del editor. vidir eliminará los objetos asociados con los números que faltan y moverá los objetos asociados con los números que quedan.


Pruebas

Yo primero usaría esta solución para replicar la estructura del directorio:

cp -a --attributes-only /mountpoint/ /guinea_pig_dir/

y prueba el procedimiento en los archivos vacíos resultantes. Esto debería revelar problemas (si hay alguno) y, con suerte, permitir mejorar el método.


Posibles problemas

  1. vidir se niega a trabajar con algunos caracteres no estándar.

  2. En general, el orden de los objetos es importante. Hay algunas trampas que generan objetos como foo~ o foo~1, foo~2 cuando hay una colisión con foo. Usted "contratará" su árbol de directorios de una manera que no debería generar colisiones, sin embargo, no he investigado todos los escenarios posibles. Realmente creo que deberías experimentar con /guinea_pig_dir/ y mira lo que obtienes En caso de problemas tal vez Un listo sort Entre find y vidir ayudará.


1





A continuación se muestra un script bash que realiza esta tarea. Funciona en p. MSYS2 Bash con rsync agregado. Se toma de esta pregunta relacionada aquí:

Script para deduplicar archivos y carpetas con un sufijo particular

#!/usr/bin/bash
IFS=$'\n';
set -f
#Go deepest first to deal with copies within copied folders.
for copy in $(find . -regextype posix-egrep -regex "^.*\ \([0-9]+\)\s*(\.[^/.]*)?$" | awk '{print length($0)"\t"$0}' | sort -rnk1 | cut -f2-); do
    orig=$(rev <<< "$copy" | sed -E 's/\)[0-9]+\(\ //' | rev)
    if [ "$orig" != "$copy" ]; then
        if [ -f "$orig" ]; then
            if [ -f "$copy" ]; then
                echo "File pair: $orig $copy"
                if diff -q "$orig" "$copy" &>/dev/null; then
                    echo "Removing file: $copy"
                    rm -f "$copy";
                fi
            fi           
        fi
        if [ -d "$orig" ]; then
            if [ -d "$copy" ]; then
                echo "Folder pair: $orig $copy"
                if rmdir "$copy" &>/dev/null; then
                    #If the "copy" was an empty directory then we've removed it and so we're done.
                    echo "Removed empty folder: $copy"
                else
                    #Non-destructively ensure that both folders have the same files at least.                    
                    rsync -aHAv --ignore-existing "$orig/" "$copy" &>/dev/null
                    rsync -aHAv --ignore-existing "$copy/" "$orig" &>/dev/null
                    if diff -qr "$orig" "$copy" &>/dev/null; then
                        echo "Removing folder: $copy"
                        rm -rf "$copy";
                    fi            
                fi
            fi
        fi
    fi
done
unset IFS;
set +f

0