2012-05-29 50 views
2

SCons提供了一個Zip構建器來從文件組生成壓縮文件。 例如,假設我們有一個看起來像這樣的文件夾foo如何使SCons不在zip文件中包含基本目錄?

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 

但是,假設我們使用的是一個VariantDir的酒吧,其中包含foo:

bar/ 
bar/foo/ 
bar/foo/foo.txt 

因爲我們是在一個VariantDir,我們仍然使用同樣的命令來創建壓縮文件,即使它有稍微不同的效果:

env.Zip('foo.zip', 'foo/') 

由此產生的zip文件:

$ unzip -l bar/foo.zip 
Archive: bar/foo.zip 
    bar/foo/ 
    bar/foo/foo.txt 

問題是zip中每個文件的額外bar/前綴。如果這不是SCons,簡單的解決方案是cd到bar並從那裏撥打電話,如cd bar; zip -r foo.zip foo/。然而,這對SCons來說很奇怪/困難,並且無論如何看起來都非常不像SCONS。有更好的解決方案嗎?

回答

5

您可以創建完成此任務的SCons構建器。我們可以使用標準的Python zip文件來創建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}) 

調用它就像正常使用SCons Zip

env.ZipBetter('foo.zip', 'foo/') 
1

目錄確實可以用SCons的一個挑戰。假設文件處於'in project'中,有幾種不同的方式可以指定要包含在Zip()文件中的文件的目錄:

  1. 相對於根項目目錄,帶'#'的路徑。此選項將包括完整的目錄,就像您提到的相對於特定SConscript文件的
  2. 一樣。指定相同目錄中的文件,或者指定與SConscript相關的子目錄。

聽起來像你想要第二個選項。你有一個SCONSCRIP文件在你想壓縮的相同目錄下,foo在你的情況下?即使對於variant_dir也是如此。

+0

這個問題不指定zip文件的目錄,它是我想補充...目錄不,我沒有在一個SConscript文件目錄。該目錄正在創建時創建,然後我想在原地壓縮其中一個創建的文件夾。 – Xymostech

+0

@Xymostech,對,我重新回答了答案。我知道你指的是將文件/目錄添加到壓縮文件中。您可以使用從構建器返回的目標,而不是指定目錄。如果你包含SConscript,我可以看看。 – Brady

+0

我試過使用從生成器返回,並且仍然無法正常工作。代碼如下:https://gist.github.com/2822868 – Xymostech

相關問題