Comment fusionner des dossiers en double ayant une structure en «noms (1)», «noms (1) (1)», etc.

1

La synchronisation entre Google Filestream, Google Drive et Synology CloudSync a tout gâché et il me reste des centaines de dossiers en double avec le nom du dossier suivi d'un "(1)" ou d'un "(2)", etc. jusqu'à "(1) (1) (1)".

Connaissez-vous un programme ou un script pouvant fusionner ces dossiers?

Exemple de structure de dossier de niveau supérieur:

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)

Comme les sous-dossiers ont parfois aussi le même problème, le programme ou le script doit pouvoir fusionner les dossiers qui suivent ce modèle de nommage pour tous les sous-dossiers, par exemple:

Exemple de dossiers de 2e niveau:

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

La meilleure solution me permettrait également de déplacer des fichiers au lieu de les copier car la copie de fichiers prend beaucoup de temps, mais le déplacement est presque instantané.

Liste des choses que j'ai déjà essayées, mais aucune d'entre elles ne peut traiter la structure de dossiers "name (1)" (que je peux dire jusqu'à présent), et toutes copient des fichiers au lieu de les déplacer:

  • WinMerge pour Windows 10 & lt; - étrangle lorsque vous essayez de copier des fichiers de disque Google (renvoie quelque chose du type "Commande DOS non prise en charge"
  • Fusion pour MacOS. & lt; - lent.
  • Terminal avec commande "idem" sous OS X & lt; - Meilleure option jusqu'à présent.

Merci de votre aide!

Josh
la source
Si je vous ai bien compris, le déplacement de fichiers dans votre cas via la connexion Internet prendra le même temps que leur copie. Vous confondez avec le déplacement de fichiers par exemple dans une partition HD, c'est rapide. Les déplacer entre des partitions, des disques durs, des ordinateurs personnels, etc. prend généralement beaucoup plus de temps (sans tenir compte des exceptions avec certaines configurations).
Albin
Merci, j'ai enlevé le peu de ma connexion Internet parce que c'est étranger. Lorsque vous déplacez des fichiers dans Google et Mac OS, les flux de fichiers Google ressemblent à ceux d'une partition HD: si vous déplacez des fichiers, le système d'exploitation ne modifie généralement que les pointeurs pointant sur le fichier, mais si vous les copiez, Ensuite, le système d’exploitation copie généralement les données dans un nouvel emplacement du lecteur. Dans ce cas, la copie prend encore plus de temps car le disque dur est connecté via Internet. À votre santé!
Josh
Salut. Je travaille sur un script pyhton pour résoudre spécifiquement votre question. C'est raisonnablement prêt, mais malheureusement, je ne peux pas passer plus de temps à apporter les (importantes) finitions jusqu'au lundi, = / puisque je voyagerai. Si vous tombez sur une réponse avant cela, eh bien, c'est bien pour vous = D, mais si vous n'en trouvez pas, je peux terminer et l'afficher ici comme réponse =). Bonne journée.
Vinícius M

Réponses:

1

C'est l'approche que j'essayerais sous Linux. Je n'ai aucune expérience de Google Filestream, de Google Drive ni de Synology CloudSync, je ne peux donc pas dire si la solution peut être appliquée. J'espère néanmoins que cela vous donnera au moins quelques idées.


Hypothèses

  • vous pouvez monter le partage dans votre arborescence de répertoires, mv, cp et d'autres outils sains peuvent travailler avec des répertoires comme s'ils étaient locaux;
  • fichiers (ou répertoires) avec des chemins qui deviennent identiques après avoir supprimé tout (N) les chaînes sont en fait des instances du même fichier (répertoire);
  • les instances du même fichier ne doivent en laisser qu'un;
  • les instances du même répertoire doivent fusionner leur contenu dans un seul répertoire;
  • vous pouvez utiliser tous les outils que j'utilise ici.

Procédure

Veuillez lire toute la réponse avant de tenter quoi que ce soit.

Je pense que certaines étapes pourraient être écrites sous forme de script, mais puisque la solution est très expérimental , mieux vaut le faire à la main, étape par étape, en faisant attention à ce qui se passe.

  1. Dans une coquille cd au point de montage et invoquer find . | vidir -; utilisez un éditeur de texte de votre choix, par exemple kate, comme ça:

    find . | EDITOR=kate vidir
    

    Cela ouvrira l'éditeur avec une liste de tous les objets, chacun avec son propre numéro devant. Lorsque vous modifiez le contenu, enregistrez le fichier (temporaire) et fermez l'éditeur, toutes les modifications sont appliquées. En général, voici ce que vous pouvez faire:

    • changer les chemins pour déplacer (renommer) des fichiers ou des répertoires;
    • supprimer des lignes pour supprimer des fichiers ou des répertoires;
    • échangez deux ou plusieurs numéros en fichiers d'échange (vous n'en aurez pas besoin).

    N'enregistrez le fichier que si vous êtes certain que le nouveau contenu décrit l'arborescence de répertoires que vous souhaitez obtenir.

  2. Copiez le contenu de l'éditeur dans un autre fichier. Le but est de travailler avec et de coller le résultat (et de le sauvegarder) uniquement lorsque vous êtes certain de bien faire les choses. Les étapes suivantes font référence au nouveau fichier, sauf indication contraire explicite.

  3. Utilisation sed ou tout autre outil pour se débarrasser de tout (N) cordes (notez l'espace de début). A ce stade, vous devriez avoir des chemins "propres", beaucoup d’entre eux se produiront plus d’une fois (avec des nombres différents donnés par vidir ).

  4. Utilisation sort -k 2 trier selon ces chemins. Grâce à -s l'ancien Analysis devrait toujours précéder l'ancien Analysis (1).

  5. Utilisation uniq -f 1 déposer les chemins dupliqués. Maintenant, tout chemin devrait se produire une fois.

  6. Revérifiez la santé de la structure de répertoire encodée dans le résultat.

  7. Collez le résultat dans l'éditeur d'origine, enregistrez le fichier et quittez l'éditeur. vidir supprimera les objets associés aux nombres manquants et déplacera les objets associés aux nombres laissés.


Essai

Je voudrais d'abord utiliser cette solution pour répliquer la structure de répertoire:

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

et testez la procédure sur les fichiers vides résultants. Cela devrait révéler des problèmes (le cas échéant) et permettre, espérons-le, d'améliorer la méthode.


Problèmes possibles

  1. vidir refuse de travailler avec des caractères non standard.

  2. En général, l'ordre des objets est important. Il y a peu de pièges qui génèrent des objets comme foo~ ou foo~1, foo~2 quand il y a une collision avec foo. Vous allez "contracter" votre arborescence de répertoires de manière à ne générer aucune collision, mais je n'ai pas encore étudié tous les scénarios possibles. Je pense vraiment que vous devriez expérimenter /guinea_pig_dir/ et voyez ce que vous obtenez. En cas de soucis peut être un habile sort entre find et vidir aidera.

Kamil Maciorowski
la source
1

Vous trouverez ci-dessous un script bash qui effectue cette tâche. Cela fonctionne par exemple MSYS2 Bash avec rsync ajouté. Il est tiré de cette question connexe ici:

Script de déduplication de fichiers et de dossiers avec un suffixe particulier

#!/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
cfp
la source
Comment définirais-je un répertoire de départ dans ce script? Quand je le testerai et lors du déploiement final, je ne veux que cela fonctionne avec un sous-ensemble spécifique de mes fichiers. Exemple: 'G: \ My Drive \ Deduplicate_Test_Folder' PS: Merci pour l'incroyable réponse!
Josh
Il suffit de commencer dans ce dossier. (C'est à dire. cd Là.)
cfp