只压缩一个目录中的文件
我有一个路径是 /home/mine/new,这里面有一些文件和子目录。我想把这个路径下的文件压缩成一个 ZIP 文件,也就是说我希望压缩包里只包含 /new/file1
、new/file2
等文件。
我试过这样做:
import zipfile
import os,glob
def zipfunc(path, myzip):
for path,dirs, files in os.walk(path):
for file in files:
if os.path.isfile(os.path.join(path,file)):
myzip.write(os.path.join(os.path.basename(path), file))
if __name__ == '__main__':
path=r'/home/ggous/new'
myzip = zipfile.ZipFile('myzipped.zip', 'w')
zipfunc(path,myzip)
myzip.close()
但是它给了我一个错误提示
没有这样的文件或目录 new/file.doc
3 个回答
0
看起来可能是因为 zipfile.ZipFile.write()
这个方法需要一个完整的路径,而不是一个相对路径或者不完整的路径。你可以试着确保在压缩文件之前,使用的是完整的路径:
def zipfunc(path, myzip):
for path,dirs, files in os.walk(path):
for file in files:
curpath = os.path.abspath(os.path.join(path, file))
if os.path.isfile(curpath):
myzip.write(curpath)
0
这是因为 os.walk
会深入到子目录中(而你的路径连接逻辑没有正确处理这个情况)。如果你不想进入子目录的话,可以用 glob.glob
来代替 os.walk
:
from os import path
import os
directory = r'/home/ggous/new'
for f in os.listdir(directory):
if path.isfile(f):
zipfile.write(os.path.basename(f), f)
2
你在使用 os.path.basename
这个函数处理路径变量。这意味着,如果你想压缩文件 new/dir1/file1
,你会把路径中的 new/
部分去掉,最后得到 dir1/file1
,但这个路径在你当前的目录下并不有效。
如果你直接去掉对 os.path.basename
的调用,文件就会正确地被压缩:
myzip.write(os.path.join(path, file))
...不过这样可能不是你想要的压缩包路径。如果你从顶层目录内部开始使用 os.walk
,你可能会得到你想要的结果:
if __name__ == '__main__':
path=os.path.join(os.getcwd(), 'new')
myzip = zipfile.ZipFile('myzipped.zip', 'w')
# Change into the top level directory.
os.chdir(path)
zipfunc('.',myzip)
myzip.close()
假设有这样的文件结构:
/home/lars/new
file1
file2
dir1/
file1
file2
file3
这样会创建一个看起来像这样的压缩包:
Archive: myzipped.zip
Length Date Time Name
--------- ---------- ----- ----
29 11-02-2011 09:14 file1
29 11-02-2011 09:14 file2
29 11-02-2011 09:14 dir1/file3
29 11-02-2011 09:14 dir1/file1
29 11-02-2011 09:14 dir1/file2
--------- -------
145 5 files
如果你真正的目标只是压缩顶层的文件,而不想进入任何子目录,那么其实你不需要使用 os.walk
。你可以直接用 os.listdir
,再用 os.path.isfile
来确保你处理的是文件而不是子目录。