Forçando o rsync a converter nomes de arquivos em minúsculas

4

Estamos usando rsync para transferir alguns (milhões) arquivos de um servidor Windows (NTFS / CYGWIN) para um servidor Linux (RHEL). Gostaríamos de forçar todos os nomes de arquivos e diretórios na caixa do Linux a serem minúsculos.

Existe uma maneira de fazer rsync converter automaticamente todos os nomes de arquivos e diretórios para minúsculas? Por exemplo, digamos que o sistema de arquivos de origem tenha um arquivo chamado:

/foo/BAR.gziP

O Rsync criaria (no sistema de destino)

/foo/bar.gzip

Obviamente, com o NTFS sendo um sistema de arquivos insensitivo a maiúsculas e minúsculas, não pode haver conflitos ...

Falhando na disponibilidade de uma opção rsync , existe uma compilação aprimorada ou alguma outra maneira de obter esse efeito? Talvez uma opção de montagem no CYGWIN? Talvez uma opção de montagem similar no Linux?

Seu RHEL, no caso que importa.

    
por SvrGuy 14.04.2012 / 18:25

3 respostas

2

Você pode alterar o caso dos nomes de arquivos resultantes no servidor de destino após o rsync. Eu não tentaria fazer isso a meio da transferência (no caso de você precisar reiniciar a cópia). Quanto a fazer a mudança no lado do linux, você precisa determinar se há algum conflito. Você também precisará determinar se precisa que o caso dos nomes de diretório seja alterado. Todos os nomes serão únicos? Se assim for, um script find apropriado associado ao comando tr ou rename poderia fazer o trabalho ...

# Examples - Don't run directly
'rename 'y/A-Z/a-z/' *' # would change case on files within a directory.
    
por 14.04.2012 / 18:51
2

Você pode montar um sistema de arquivos sem distinção entre maiúsculas e minúsculas. Veja este post .

Além disso, esta página sugere a criação de uma imagem de disco do tipo FAT32 e sua montagem. O fs criado não diferencia maiúsculas de minúsculas em nenhuma partição do Windows.

Usar essa solução eliminará a necessidade de converter todos esses milhões de arquivos em minúsculas.

    
por 14.04.2012 / 20:08
2

Não é a solução mais elegante, mas você pode usar LD_PRELOAD para substituir as chamadas de sistema relevantes e forçar tudo para minúsculas. Eu achei divertido, então fiz uma pequena prova de conceito e ...

> ls in out
in:
CyltApJik  keumyomDu  LidusIcweo  spydjiPa  SycsEyror  tusUngEg

out:
> rsync -av in/ --rsync-path='env LD_PRELOAD=$PWD/lowercase.so rsync' localhost:out/ 
sending incremental file list
./
CyltApJik
LidusIcweo
SycsEyror
keumyomDu
spydjiPa
tusUngEg

sent 372 bytes  received 129 bytes  1002.00 bytes/sec
total size is 0  speedup is 0.00

> ls out
cyltapjik  keumyomdu  lidusicweo  spydjipa  sycseyror  tusungeg

E aqui está a amostra, que pode levar algumas iterações para se tornar boa o suficiente para sincronizar tudo.

> cat lowercase.c 
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#define __USE_GNU
#include <dlfcn.h>

static int (*real_lstat) (const char *, struct stat *) = NULL;
static int (*real_rename)(const char *, const char *)  = NULL;

char * lowered(const char * string)
{
        char * low = strndup(string, 2048);
        char * c;
        if (low == NULL) return NULL;
        for (c = low; *c; c++) {
                *c = tolower(*c);
        }
        return low;
}

int lstat(const char * path, struct stat * buf)
{
        int ret = 0;
        if (real_lstat == NULL) {
                real_lstat = dlsym(RTLD_NEXT, "lstat");
        }
        ret = real_lstat(path, buf);
        if (ret == 0) return ret;
        ret = real_lstat(lowered(path), buf);
        return ret;
}

int rename (__const char *__old, __const char *__new)
{
        if (real_rename == NULL) {
                real_rename = dlsym(RTLD_NEXT, "rename");
        }
        return real_rename(__old, lowered(__new));
}
> gcc -ldl -fPIC -shared -o lowercase.so lowercase.c
    
por 31.10.2012 / 19:11