强制 rsync 将文件名转换为小写

强制 rsync 将文件名转换为小写

我们正在rsync将一些(数百万)文件从 Windows(NTFS/CYGWIN)服务器传输到 Linux(RHEL)服务器。我们希望强制 Linux 机器上的所有文件和目录名称都为小写。

有没有办法rsync自动将所有文件和目录名称转换为小写?例如,假设源文件系统有一个名为的文件:

/foo/BAR.gziP

Rsync 将在目标系统上创建

/foo/bar.gzip

显然,由于 NTFS 是不区分大小写的文件系统,因此不会发生任何冲突......

如果没有可用的rsync选项,是否有增强版本或其他方法可以实现此效果?也许是 CYGWIN 上的安装选项?也许是 Linux 上的类似安装选项?

如果有必要的话,它是 RHEL。

答案1

您可以在目标服务器上更改结果文件名的大小写rsync。我不会尝试在传输过程中执行此操作(以防您需要重新启动复制)。至于在 Linux 端进行更改,您需要确定是否存在任何冲突。您还需要确定是否需要更改目录名称的大小写。所有名称都是唯一的吗?如果是这样,适当的脚本findtrrename命令相结合就可以完成这项工作……

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

答案2

您可以挂载不区分大小写的文件系统。查看这个帖子

此外,此页面建议创建类型的磁盘映像FAT32并安装它。创建的 fs 将不区分大小写,例如任何 Windows 分区。

使用这样的解决方案将消除将这数百万个文件全部转换为小写的需要。

答案3

虽然不是最优雅的解决方案,但您可以使用 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 <ctype.h>
#include <string.h>
#include <sys/stat.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

相关内容