若干个文件为一组分别打包成压缩包

需求

最近要在互联网上分享一些资源,但因为侵权,百度网盘限制直接分享。如果将整体打包为一个压缩包对方下载又太慢了,而如果分别压缩的话文件名会暴露,也没有意义。因此想每 5 或 10 个为一组进行压缩,这样接收者的下载体验也会更好。

实现

首先,文件的命名自然需要有规律,大致是按照 num.*.ext 这样的格式进行的,如图所示。

这样可以为后续的排序提供方便。

首先,RAR 压缩多个文件到一个文件的命令如下:

1
WinRAR.exe a -ibck rarfile file1 file2 file3

其中,-ibck 参数是后台运行的意思,rarfile 是压缩后压缩文件的名字, filen 是待压缩的文件。

一开始是尝试使用批处理进行的,但批处理不支持数组,因此不能一次将若干个文件名作为压缩命令的变量。当然也不是不可以,但需要非常长的一段 for 循环代码来模拟数组,不考虑。

有一些折中的办法,比如知乎上如何压缩每 100 份文件到一个压缩包且压缩包之间互相独立? - Optimistices 的回答 所述,借助 7z 可以读取 txt 文件作为文件列表的特性。先获取文件夹下所有文件名存储到 txt 文件中,然后用第三方工具分割,在依次压缩。但这样终究是人工干预多了些。

最后,还是选择了 Python。Python 有完备的文件库,也可以很方便的处理字符串,因此自然地想到使用 Python 语言来处理这一问题。

首先安装好 Python 环境,然后安装好必备的包。具体代码如下,保存为 zipfile.py,说明见注释。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# 导入库
import os
import math

# 全局变量
List_Fname = []

"""函数区"""
# 获取文件夹下的文件名


def listdir(path, list_name,ext):
filelist = os.listdir(path)
for file in os.listdir(path):
if file[-4:] == ext: # 字符串切片,提取指定后缀的文件
list_name.append(file)
list_name = list_name.sort(key=lambda x: int(x.split('.')[0]))# 按照.分割文件名,并取第1节字符转int排序
return list_name


"""主函数区"""
def main():
rar_path="C:\Program Files\WinRAR\WinRAR.exe" # RAR可执行程序路径,也可以选择添加到环境变量
root_dir="E:\\仓库\\有声书\\出版图书" # 需要压缩的文件夹的绝对路径
source_path="大宋帝国三百年" # 需要压缩的文件夹的名字
num=10 # 每个压缩包中的文件数量,下面的示例是9
ext=".m4a" # 需要整理的文件格式

source_dir=root_dir+"\\"+source_path
listdir(source_dir, List_Fname,ext)
# 创建压缩包文件存储路径及文件名
outdir=source_dir+"\\outzip\\"
direxist='IF NOT EXIST "%s" MD "%s"'%(outdir,outdir)
print(direxist)
unzip_dir=''
lens=len(List_Fname)
lensa=math.floor(lens/num) #向下取整(是的,引入math包就为了这一下)
for i in range(0,lensa):
start=i*(num)
endt=(i+1)*num-1
files=List_Fname[start:endt+1]
outfile=str(start+1)+'_'+str(endt+1)
rar_command='"'+rar_path+'"'+' a -ibck "'+outdir+outfile+'"'
for j in range(0,len(files)):
rar_command=rar_command+' "'+unzip_dir+files[j]+'"'
print(rar_command)
# os.system(rar_command) # 这一句注释掉了,因为rar_path中可能包含空格,不能直接在这里运行批处理命令
# 剩下的一些文件
i=i+1
start=i*(num)
files=List_Fname[start:lens+1]

outfile=str(start+1)+'_'+str(lens)
rar_command='"'+rar_path+'"'+' a -ibck "'+outdir+outfile+'"'
if((lens-1)==start):
j=0
rar_command=rar_command+' "'+unzip_dir+files[j]+'"'
else:
for j in range(0,len(files)):
rar_command=rar_command+' "'+unzip_dir+files[j]+'"'

print(rar_command)


"""主函数调用"""
main()

使用

需要注意的是,由于命令路径有空格,因此直接运行该文件并不能很好的完成任务。

在任意位置启动 “命令提示符” 窗口

1
开始→运行→CMD

然后执行

1
python zipfile.py > zipfile.bat

既将 Python 中打印的命令输出到批处理文件中。然后将生成的批处理文件移动到要压缩文件的同级目录下,双击运行即可。
压缩过程会在后台进行,如果不添加 -ibck 参数,那么每次压缩 RAR 运行框都会跳出来抢夺窗口焦点。压缩后的文件示例如图:

生成的压缩包内的目录树如下所示:

1
2
3
4
5
6
1_10.rar
├ file1.m4a
├ file2.m4a
├ file3.m4a
├ ……
└ filen.m4a

这样,直接解压各压缩文件又可以还原第一张图片所示的音频文件。