根据文件数量和深度生成随机目录/文件

2 投票
4 回答
4601 浏览
提问于 2025-04-15 15:00

我想对一些版本控制系统(VCS)软件进行性能分析,为此我需要生成一组随机文件,并把它们放在随机排列的文件夹里。我正在用Python写这个脚本,但我想问的是:我该如何生成一个随机的目录树,每个目录下有平均数量的子目录,并且每个目录里的文件数量分布比较广泛呢?

澄清一下:我并不是在比较不同的版本控制系统格式(比如SVN、Git或Hg),而是想分析处理SVN(以及将来其他)工作副本和仓库的软件。

我希望的限制条件是可以指定文件的总数(我们称之为'N',大概在1万到10万之间)和目录结构的最大深度('L',大概在2到10之间)。我不在乎每一层生成多少个目录,也不想每个目录里只有1个文件,或者把10万个文件都放在一个目录里。

关于文件分布我有点不确定,因为我不知道版本控制系统(特别是SVN)在非常均匀的结构和非常不均匀的结构下表现如何。不过,如果我能想出一个算法,不会因为数量大而“平均分配”,那就太好了。

我最初的想法是:用某种方法生成目录树,然后均匀地在树中填充文件(对每个目录一视同仁,不考虑嵌套)。我简单算了一下,如果有'L'层,每个目录有'D'个子目录,每个目录大约有sqrt(N)个文件,那么大概会有D^L个目录,所以N大约等于sqrt(N)*(D^L),也就是D大约等于N的1/(2L)次方。现在我有了'D'的一个大致值,我该如何生成这个树呢?我该如何填充文件呢?

如果能给我一些关于可以使用的算法的好资源的指引,我将非常感激。我搜索到的内容大多是漂亮的应用程序或Flash动画。

4 个回答

0

你的问题比较长,也涉及很多内容,但我觉得主要是想要一个具有特定统计特性的随机数生成器。

如果你不喜欢Python自带的随机数生成器,可以看看pypi上其他的一些统计包,或者如果你想要更强大的功能,可以考虑GNU科学库的Python绑定。

http://sourceforge.net/projects/pygsl/

http://www.gnu.org/software/gsl/

3

我最近写了一个小的Python包,叫做randomfiletree,它可以生成随机的文件和目录结构。代码和使用手册可以在https://github.com/klieret/randomfiletree找到。

这个算法会遍历一个已有的文件树,然后在每个子文件夹里根据一个高斯分布(也就是一种数学模型)生成一定数量的文件和目录。这个过程会不断重复。

基本上,它使用的东西像这样:

def create_random_tree(basedir, nfiles=2, nfolders=1, repeat=1,
                       maxdepth=None, sigma_folders=1, sigma_files=1):
    """
    Create a random set of files and folders by repeatedly walking through the
    current tree and creating random files or subfolders (the number of files
    and folders created is chosen from a Gaussian distribution).

    Args:
        basedir: Directory to create files and folders in
        nfiles: Average number of files to create
        nfolders: Average number of folders to create
        repeat: Walk this often through the directory tree to create new
            subdirectories and files
        maxdepth: Maximum depth to descend into current file tree. If None,
            infinity.
        sigma_folders: Spread of number of folders
        sigma_files: Spread of number of files
    Returns:
       (List of dirs, List of files), all as pathlib.Path objects.
    """
    alldirs = []
    allfiles = []
    for i in range(repeat):
        for root, dirs, files in os.walk(str(basedir)):
            for _ in range(int(random.gauss(nfolders, sigma_folders))):
                p = Path(root) / random_string()
                p.mkdir(exist_ok=True)
                alldirs.append(p)
            for _ in range(int(random.gauss(nfiles, sigma_files))):
                p = Path(root) / random_string()
                p.touch(exist_ok=True)
                allfiles.append(p)
            depth = os.path.relpath(root, str(basedir)).count(os.sep)
            if maxdepth and depth >= maxdepth - 1:
                del dirs[:]
    alldirs = list(set(alldirs))
    allfiles = list(set(allfiles))
    return alldirs, allfiles

这是一种比较简单粗暴的方法,不过如果有人感兴趣的话,也可以进一步开发这个模块。

5

为什么不下载一些真正的开源项目来用呢?

你有没有想过这些文件里都包含了什么?那些也是随机的数据吗?

撰写回答