Назад | Перейти на главную страницу

Принуждение rsync к преобразованию имен файлов в нижний регистр

Мы используем rsync для передачи некоторых (миллионов) файлов с сервера Windows (NTFS / CYGWIN) на сервер Linux (RHEL). Мы хотели бы, чтобы все имена файлов и каталогов в поле Linux были строчными.

Есть ли способ сделать rsync автоматически преобразовывать все имена файлов и каталогов в нижний регистр? Например, предположим, что в исходной файловой системе был файл с именем:

/foo/BAR.gziP

Rsync создаст (в целевой системе)

/foo/bar.gzip

Очевидно, что NTFS - файловая система без учета регистра, конфликтов быть не может ...

В случае отсутствия rsync вариант, есть ли улучшенная сборка или какой-то другой способ добиться такого эффекта? Возможно, вариант монтирования на CYGWIN? Возможно, аналогичный вариант монтирования в Linux?

Его RHEL, если это имеет значение.

Не самое элегантное решение, но вы можете использовать LD_PRELOAD, чтобы переопределить соответствующие системные вызовы и перевести все в нижний регистр. Я подумал, что это весело, поэтому сделал небольшое доказательство концепции и ...

> 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

И вот образец, который может занять несколько итераций, чтобы стать достаточно хорошим, чтобы синхронизировать все это.

> 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

Вы можете смонтировать файловую систему без учета регистра. смотреть на эта почта.

Также на этой странице предлагается создать образ диска типа FAT32 и монтируем его. Созданный файл fs будет нечувствителен к регистру, как и любой раздел Windows.

Использование такого решения избавит от необходимости преобразовывать все эти миллионы файлов в нижний регистр.

Вы можете изменить регистр имен файлов на целевом сервере. после файл rsync. Я бы не стал пытаться делать это в середине передачи (на случай, если вам нужно перезапустить копию). Что касается внесения изменений на стороне Linux, вам необходимо определить, есть ли какие-либо конфликты. Вам также нужно будет определить, нужно ли вам изменить регистр имен каталогов. Все имена будут уникальными? Если да, то соответствующий find сценарий в сочетании с tr или rename команда могла бы сделать работу ...

# Examples - Don't run directly
`rename 'y/A-Z/a-z/' *` # would change case on files within a directory.