根据文件数量和深度生成随机目录/文件
我想对一些版本控制系统(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 个回答
你的问题比较长,也涉及很多内容,但我觉得主要是想要一个具有特定统计特性的随机数生成器。
如果你不喜欢Python自带的随机数生成器,可以看看pypi上其他的一些统计包,或者如果你想要更强大的功能,可以考虑GNU科学库的Python绑定。
我最近写了一个小的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
这是一种比较简单粗暴的方法,不过如果有人感兴趣的话,也可以进一步开发这个模块。
为什么不下载一些真正的开源项目来用呢?
你有没有想过这些文件里都包含了什么?那些也是随机的数据吗?