我编写了一个脚本,该脚本获取文件夹,并使用Python的多处理池库将它们组合到最大尺寸500MB的文件中。脚本将文件夹中的文件列表列出,并将其分为16个列表,每个列表都映射到一个过程。在每个过程中,由每个列表中的一组文件组成一个组合的临时文件。在获得所有这16个文件后,我将这16个文件顺序结合并删除临时文件。 IM在带有Ext4文件系统的CentOS系统上运行此操作,然后我通过了一个930 MB的文件夹,其中186147文件分布在50个子文件夹中,它给了我一个文件作为输出,大小为346 MB。我感到困惑的是,文件大小如何减少。
请注意,这186147文件中的每个文件都在开始时在最终文件创建期间忽略了一个额外的标头,但是只有标头的文件仅为233字节。
。为了检查我的脚本是否正确,我检查了组合文件(3083015(中的行总数,并且与186147文件(3269162(中的行数量匹配 - 标头数(186147(。我还试图猫单文件,而行似乎已经完成,但是我没有浏览整个文件。
我在这里缺少什么吗?
这是我使用的并行函数:
curr_write_file_name = os.path.join(output_folder, str(list_index) + '_' + "00000.flows")
curr_write_file = open(curr_write_file_name, 'w')
curr_write_file.write(header)
curr_write_count = 1
for curr_file in file_list:
print('Processing', curr_file)
netflow_read = open(curr_file, 'r')
for index, line in enumerate(netflow_read):
if index == 0:
continue
else:
curr_write_file.write(line)
if os.stat(curr_file).st_size >= 500000000:
curr_write_file.close()
curr_write_file_name = os.path.join(output_folder, str(list_index) + '_' + str(curr_write_count).zfill(5) + '.flows')
curr_write_file = open(curr_write_file_name, 'w')
curr_write_count = curr_write_count + 1
curr_write_file.write(header)
netflow_read.close()
这是相应的主:
if __name__=='__main__'
dataFileList = []
for dirPath, dirNames, fileNames in os.walk(str(sys.argv[1])):
# Since the filtering occurs parallel, sorting the files has no benefit
dirNames.sort()
fileNames.sort()
dataFileList = dataFileList + [os.path.join(dirPath, fileName) for fileName in fileNames if fileName.endswith('.flows')]
noOfProcesses = os.cpu_count()*2 # To create a maximum of no_of_cores*2 processes
process_pool = mp.Pool(noOfProcesses) # To create a parallel pool of noOfProcesses processes
file_split_number = int(len(dataFileList)/noOfProcesses)
dataFile_list_of_lists = [(dataFileList[x:x+file_split_number], x) for x in range(0, len(dataFileList), file_split_number)]
process_pool.map(worker_process_combine_set, dataFile_list_of_lists) # To map the processes to the files in the list and split them
stage_1 = time.time()
print('Completed first stage combining successfully in', stage_1 - start_time, 'seconds')
process_pool.close()
process_pool.join()
# sequential combining
finalFiles = combine_final()
print('Completed combining files successfully in', time.time() - start_time, 'seconds')
这篇文章是为ext4文件系统编写的,这是Linux上最多分布的默认文件系统,您可以使用以下方式检查当前文件系统:
df -T / | awk '{print $2}' | tail -1
即使很多文件系统都可以使用(不支持块子分配(,也可能不适用于其他文件系统。
。文件的大小和此文件分配的 disk Space 的数量是2个不同的概念。使用特定文件系统安装的磁盘存储的统一是文件系统的块大小。每个文件都是通过使用一定数量的块来存储的。但是最后一个块并不总是满满,您的文件系统分配了剩余的空间以尊重此规则。文件的数据占据了一个代表块大小的数量的空间。这就是为什么如果您通过串联将几个文件转换为一个文件,则保存磁盘的空间。
对于您的情况,将186147
文件转换为一个文件:如果您考虑最后一个块中的字节数量并不是真正使用并遵循统一的法律,则可以平均节省186147*sizeof(block)/2
字节,并且最多可用于磁盘的186147*sizeof(block)
字节存储不计算每个文件的保存元数据和架空文件系统。
对于大多数文件系统,块的大小为4KB,也就是说4096字节。在这里,您可以平均节省(4096/2)*186147//(1024**2) = 363MB
和最多4096*186147//(1024**2) = 727MB
。
通过执行:
查看文件系统的块大小device=$(df -T / | awk '{print $1}' | tail -1)
dumpe2fs "${device}" | grep 'Block size'
用:
对其进行测试echo 'a' > filea.txt; echo 'b' > fileb.txt; more *; ls -sh *
输出:
::::::::::::::
filea.txt
::::::::::::::
a
::::::::::::::
fileb.txt
::::::::::::::
b
4,0K filea.txt 4,0K fileb.txt
然后:
cat * > file.txt; more *; ls -sh *
输出:
::::::::::::::
filea.txt
::::::::::::::
a
::::::::::::::
fileb.txt
::::::::::::::
b
::::::::::::::
file.txt
::::::::::::::
a
b
4,0K filea.txt 4,0K fileb.txt 4,0K file.txt
file.txt
的大小是4KB
不是8KB = sizeof(fileb.txt) + sizeof(filea.txt)
。
如果创建一个4097字节的文件,将分配2个文件系统块。请参阅:
dd if=/dev/zero of=file.txt bs=1 count=4097 &> /dev/null
ls -s --block-size=1 file.txt
输出:
8192 file.txt
file.txt的大小为 8192 bytes = 2*sizeof(filesystem_block)
不是 4097 bytes
。
您的文件系统的块大小是什么?因为,您会看到,最后一个块的末尾有一些未使用的空间,平均而言是半个块,如果您将其乘以文件数(186147((186147(,这可能相当于数百兆字节…