Принудительное использование 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