Python 如何使SCON在zip文件中不包含基本目录?
SCons提供了一个Zip生成器,用于从文件组生成Zip文件。 例如,假设我们有一个文件夹Python 如何使SCON在zip文件中不包含基本目录?,python,zip,scons,Python,Zip,Scons,SCons提供了一个Zip生成器,用于从文件组生成Zip文件。 例如,假设我们有一个文件夹foo,如下所示: foo/ foo/blah.txt 我们从文件夹foo创建zip文件foo.zip: env.Zip('foo.zip', 'foo/') 这将生成一个zip文件: $ unzip -l foo.zip Archive: foo.zip foo/ foo/foo.txt $ unzip -l bar/foo.zip Archive: bar/foo.zip bar/
foo
,如下所示:
foo/
foo/blah.txt
我们从文件夹foo
创建zip文件foo.zip
:
env.Zip('foo.zip', 'foo/')
这将生成一个zip文件:
$ unzip -l foo.zip
Archive: foo.zip
foo/
foo/foo.txt
$ unzip -l bar/foo.zip
Archive: bar/foo.zip
bar/foo/
bar/foo/foo.txt
但是,假设我们使用的是一个包含foo的bar的VariantDir
:
bar/
bar/foo/
bar/foo/foo.txt
由于我们使用的是VariantDir
,因此我们仍然使用相同的命令来创建zip文件,尽管它的效果略有不同:
env.Zip('foo.zip', 'foo/')
这将生成zip文件:
$ unzip -l foo.zip
Archive: foo.zip
foo/
foo/foo.txt
$ unzip -l bar/foo.zip
Archive: bar/foo.zip
bar/foo/
bar/foo/foo.txt
问题是zip中的每个文件都有额外的
bar/
前缀。如果不是SCons,那么简单的解决方案是将cd放入bar
,然后从里面用类似cd bar的东西调用zip;zip-r foo.zip foo/
。然而,这对司康人来说是很奇怪/困难的,而且至少看起来很不像司康人。有更好的解决方案吗?您可以创建一个SCons Builder来完成此任务。我们可以使用标准的Python zipfile来生成zip文件。我们利用了zipfile.write
,它允许我们指定要添加的文件,以及在zip中应该调用的文件:
zf.write('foo/bar', 'bar') # save foo/bar as bar
为了获得正确的路径,我们使用os.path.relpath
和基本文件的路径来查找整个文件的路径
最后,我们使用os.walk
遍历要添加的目录的内容,并调用前两个函数将它们正确地添加到最终的zip文件中
import os.path
import zipfile
def zipbetter(target, source, env):
# Open the zip file with appending, so multiple calls will add more files
zf = zipfile.ZipFile(str(target[0]), 'a', zipfile.ZIP_DEFLATED)
for s in source:
# Find the path of the base file
basedir = os.path.dirname(str(s))
if s.isdir():
# If the source is a directory, walk through its files
for dirpath, dirnames, filenames in os.walk(str(s)):
for fname in filenames:
path = os.path.join(dirpath, fname)
if os.path.isfile(path):
# If this is a file, write it with its relative path
zf.write(path, os.path.relpath(path, basedir))
else:
# Otherwise, just write it to the file
flatname = os.path.basename(str(s))
zf.write(str(s), flatname)
zf.close()
# Make a builder using the zipbetter function, that takes SCons files
zipbetter_bld = Builder(action = zipbetter,
target_factory = SCons.Node.FS.default_fs.Entry,
source_factory = SCons.Node.FS.default_fs.Entry)
# Add the builder to the environment
env.Append(BUILDERS = {'ZipBetter' : zipbetter_bld})
就像普通烤饼一样叫它Zip
:
env.ZipBetter('foo.zip', 'foo/')
目录对于SCON来说确实是一个挑战。假设文件位于“项目”中,有几种不同的方法可以指定要包含在Zip()文件中的文件目录,如下所示:
听起来你想要第二个选择。在您的案例中,
foo
中是否有与您要压缩的目录相同的SConscript文件?即使对于variant_dir,这也应该有效。使用构造变量“ZIPROOT”问题不是指定zip文件的目录,而是我要添加的目录。。。不,我在目录中没有SConscript文件。生成时正在创建目录,然后我想将其中一个创建的文件夹压缩到位。@Xymostech,对,我重新编写了答案。我知道您指的是要添加到zip的文件/dir。您可以使用从生成器返回的目标,而不是指定目录。如果您包含SConscript,我可以看一看。我已经尝试使用生成器的返回,但仍然不起作用。代码如下:@Xymostech,您还可以使用Package()生成器,将PACKAGETYPE设置为zip。我会测试一下,看看是否有用。@Xymostech,顺便说一句,你住在我最喜欢的城市:)我以前住在路易斯维尔,但因为家庭原因不得不搬家。