Como mesclar pastas duplicadas com a estrutura “name (1)”, “name (1) (1)” etc.

1

Sincronização entre o meu Google Filestream, o Google Drive e o Synology CloudSync e me deixei confuso e ficamos com centenas de pastas duplicadas com o nome da pasta seguido por um "(1)" ou "(2)" etc. e indo até "(1) (1) (1)".

Você conhece algum programa ou script que possa mesclar essas pastas?

Exemplo de estrutura de pastas de nível 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)

Como as subpastas às vezes também apresentam o mesmo problema, o programa ou script precisa ser capaz de mesclar pastas que seguem esse padrão de nomenclatura para todas as subpastas, por exemplo:

Exemplo de pastas de segundo nível:

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

A melhor solução também permitiria que eu movesse os arquivos em vez de copiá-los, já que leva muito tempo para copiar arquivos, mas a movimentação é quase instantânea.

Lista de coisas que eu já tentei, mas nenhuma delas pode lidar com a estrutura de pastas "name (1)" (que eu posso dizer até agora), e todas elas copiam arquivos em vez de movê-los:

  • WinMerge for Windows 10 < - engasga ao tentar copiar arquivos do Google Drive (retorna algo como "comando DOS não suportado" para eles)
  • Meld para MacOS. < - lento.
  • Terminal com o comando "idem" no OS X < - A melhor opção até agora.

Obrigado pela sua ajuda!

    
por Josh 11.07.2018 / 19:04

2 respostas

1

Esta é a abordagem que eu tentaria no Linux. Não tenho experiência com o Google Filestream, o Google Drive nem o Synology CloudSync, por isso não sei dizer se a solução pode ser aplicada. Ainda espero que isso, pelo menos, lhe dê algumas ideias.

Suposições

  • você pode montar o compartilhamento em sua árvore de diretórios, portanto, mv , cp e outras ferramentas sãs podem trabalhar com diretórios como se fossem locais;
  • arquivos (ou diretórios) com caminhos que se tornam idênticos depois que você remove todas as cadeias (N) são, na verdade, instâncias do mesmo arquivo (diretório);
  • instâncias do mesmo arquivo devem deixar apenas um arquivo;
  • instâncias do mesmo diretório devem mesclar seu conteúdo em um único diretório;
  • você pode usar todas as ferramentas que eu uso aqui.

Procedimento

Por favor, leia a resposta completa antes de tentar fazer qualquer coisa.

Acho que algumas etapas podem ser escritas como um script, mas como a solução é altamente experimental , é melhor fazer isso manualmente, passo a passo, prestando atenção no que acontece.

  1. Em um shell cd para o ponto de montagem e invoque find . | vidir - ; usar um editor de texto de sua escolha, por exemplo kate , assim:

    find . | EDITOR=kate vidir
    

    Isso abrirá o editor com uma lista de todos os objetos, cada um com seu próprio número na frente. Quando você altera o conteúdo, salva o arquivo (temporário) e fecha o editor, todas as alterações são aplicadas. Em geral, isso é o que você pode fazer:

    • alterar caminhos para mover (renomear) arquivos ou diretórios;
    • excluir linhas para remover arquivos ou diretórios;
    • troque dois ou mais números para trocar arquivos (você não precisará dele).

    Não salve o arquivo, a menos que tenha certeza de que o novo conteúdo descreve a árvore de diretórios que você deseja obter.

  2. Copie o conteúdo do editor para outro arquivo. O objetivo é trabalhar com ele e colar o resultado (e salvá-lo) apenas quando tiver certeza de que está certo. As próximas etapas referem-se ao novo arquivo, a menos que seja explicitamente indicado de outra forma.

  3. Use sed ou qualquer outra ferramenta para se livrar de todas as sequências (N) (observe o espaço à esquerda). Neste ponto, você deve obter caminhos "limpos", muitos deles ocorrerão mais de uma vez (com números diferentes dados por vidir ).

  4. Use sort -k 2 para classificar de acordo com esses caminhos. Graças a -s , o primeiro Analysis ainda deve preceder o antigo Analysis (1) .

  5. Use uniq -f 1 para eliminar caminhos duplicados. Agora, qualquer caminho deve ocorrer apenas uma vez.

  6. Verifique novamente a sanidade da estrutura de diretórios codificada no resultado.

  7. Cole o resultado no editor original, salve o arquivo e saia do editor. vidir removerá objetos associados a números ausentes e moverá objetos associados a números restantes.

Teste

Primeiro, use esta solução para replicar a estrutura de diretórios:

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

e teste o procedimento nos arquivos vazios resultantes. Isso deve revelar problemas (se houver) e, esperamos, permitir melhorar o método.

Possíveis problemas

  1. vidir se recusa a trabalhar com alguns caracteres não padrão.

  2. Em geral, a ordem dos objetos é importante. Existem algumas armadilhas que geram objetos como foo~ ou foo~1 , foo~2 quando há uma colisão com foo . Você vai "contratar" a sua árvore de diretórios de uma forma que não deve gerar colisões, ainda não investiguei todos os cenários possíveis. Eu realmente acho que você deve experimentar com /guinea_pig_dir/ e ver o que você recebe. Em caso de problemas talvez , um inteligente sort entre find e vidir ajudará.

por 13.07.2018 / 11:05
1

Abaixo está um script bash que executa esta tarefa. Funciona em, e. Bash MSYS2 com rsync adicionado. É tirado desta questão relacionada aqui:

Script para desduplicar arquivos e pastas com um sufixo específico

#!/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
    
por 03.08.2018 / 13:52