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

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

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

/foo/BAR.gziP

Rsync создаст (в системе назначения)

/foo/bar.gzip

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

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

Это RHEL, в случае, если это имеет значение.

3 ответа

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

Также на этой странице предлагается создать образ диска типа 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.

Не самое элегантное решение, но вы можете использовать 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
Другие вопросы по тегам