Zipファイルを作成したい。 Zipファイルにフォルダーを追加し、そのフォルダーに一連のファイルを追加します。
だから私はファイルが入った単一のフォルダを持つZipファイルになりたいです。
Zipファイルなどにフォルダを作成するのが悪い習慣なのかどうかはわかりませんが、Googleはこの件について何も教えてくれません。
私はこれから始めました:
def addFolderToZip(myZipFile,folder):
folder = folder.encode('ascii') #convert path to ascii for ZipFile Method
for file in glob.glob(folder+"/*"):
if os.path.isfile(file):
print file
myZipFile.write(file, os.path.basename(file), zipfile.Zip_DEFLATED)
Elif os.path.isdir(file):
addFolderToZip(myZipFile,file)
def createZipFile(filename,files,folders):
curTime=strftime("__%Y_%m_%d", time.localtime())
filename=filename+curTime;
print filename
zipFilename=utils.getFileName("files", filename+".Zip")
myZipFile = zipfile.ZipFile( zipFilename, "w" ) # Open the Zip file for writing
for file in files:
file = file.encode('ascii') #convert path to ascii for ZipFile Method
if os.path.isfile(file):
(filepath, filename) = os.path.split(file)
myZipFile.write( file, filename, zipfile.Zip_DEFLATED )
for folder in folders:
addFolderToZip(myZipFile,folder)
myZipFile.close()
return (1,zipFilename)
(success,filename)=createZipFile(planName,files,folders);
から取得: http://mail.python.org/pipermail/python-list/2006-August/396166.html
これにより、すべてのフォルダーが削除され、ターゲットフォルダー(およびそのサブフォルダー)内のすべてのファイルが単一のZipファイルに配置されます。フォルダー全体を追加することはできませんでした。
MyZipFile.writeのフォルダーへのパスをフィードすると、
IOError:[Errno 13]許可が拒否されました: '..\packed\bin'
どんな助けも大歓迎です。
関連質問: python(バージョン2.5)? を使用してフォルダーのコンテンツを圧縮するにはどうすればよいですか?)==
OK、あなたが望むものを理解した後、zipfile.write
の2番目の引数を使用するのと同じくらい簡単です。
import zipfile
myZipFile = zipfile.ZipFile("Zip.zip", "w" )
myZipFile.write("test.py", "dir\\test.py", zipfile.Zip_DEFLATED )
test.py
がdir
というディレクトリに抽出されるzipファイルを作成します
編集:Zipファイルに空のディレクトリを作成する必要がありました:それは可能です。上記のコードがzipファイルからtest.pyファイルを削除すると、ファイルはなくなりますが、空のディレクトリは残ります。
Shutilも使用できます
import shutil
Zip_name = 'path\to\Zip_file'
directory_name = 'path\to\directory'
# Create 'path\to\Zip_file.Zip'
shutil.make_archive(Zip_name, 'Zip', directory_name)
これにより、フォルダー全体がZipに配置されます。
Zipファイルにはディレクトリ構造はありません。パス名とその内容の束だけがあります。これらのパス名は、架空のルートフォルダー(Zipファイル自体)に対して相対的でなければなりません。 「../」プレフィックスは、Zipファイルでは定義された意味を持ちません。
ファイルa
があり、Zipファイル内の「フォルダー」に保存することを検討してください。 zipfileにファイルを保存するときに、ファイル名の前にフォルダー名を付けるだけです。
zipi= zipfile.ZipInfo()
zipi.filename= "folder/a" # this is what you want
zipi.date_time= time.localtime(os.path.getmtime("a"))[:6]
zipi.compress_type= zipfile.Zip_DEFLATED
filedata= open("a", "rb").read()
zipfile1.writestr(zipi, filedata) # zipfile1 is a zipfile.ZipFile instance
Zipファイルにemptyフォルダーを含めることを許可するZip実装を知りません。回避策(抽出時に無視する必要のあるZip "フォルダ"にdummyファイル名を保存する)を考えることはできますが、実装間で移植性はありません。
import zipfile
import os
class ZipUtilities:
def toZip(self, file, filename):
Zip_file = zipfile.ZipFile(filename, 'w')
if os.path.isfile(file):
Zip_file.write(file)
else:
self.addFolderToZip(Zip_file, file)
Zip_file.close()
def addFolderToZip(self, Zip_file, folder):
for file in os.listdir(folder):
full_path = os.path.join(folder, file)
if os.path.isfile(full_path):
print 'File added: ' + str(full_path)
Zip_file.write(full_path)
Elif os.path.isdir(full_path):
print 'Entering folder: ' + str(full_path)
self.addFolderToZip(Zip_file, full_path)
def main():
utilities = ZipUtilities()
filename = 'TEMP.Zip'
directory = 'TEMP'
utilities.toZip(directory, filename)
main()
私は走っています:
python tozip.py
これはログです:
havok@fireshield:~$ python tozip.py
File added: TEMP/NARF (7ª copia)
Entering folder: TEMP/TEMP2
File added: TEMP/TEMP2/NERF (otra copia)
File added: TEMP/TEMP2/NERF (copia)
File added: TEMP/TEMP2/NARF
File added: TEMP/TEMP2/NARF (copia)
File added: TEMP/TEMP2/NARF (otra copia)
Entering folder: TEMP/TEMP2/TEMP3
File added: TEMP/TEMP2/TEMP3/DOCUMENTO DEL FINAL
File added: TEMP/TEMP2/TEMP3/DOCUMENTO DEL FINAL (copia)
File added: TEMP/TEMP2/NERF
File added: TEMP/NARF (copia) (otra copia)
File added: TEMP/NARF (copia) (copia)
File added: TEMP/NARF (6ª copia)
File added: TEMP/NERF (copia) (otra copia)
File added: TEMP/NERF (4ª copia)
File added: TEMP/NERF (otra copia)
File added: TEMP/NERF (3ª copia)
File added: TEMP/NERF (6ª copia)
File added: TEMP/NERF (copia)
File added: TEMP/NERF (5ª copia)
File added: TEMP/NARF (8ª copia)
File added: TEMP/NARF (3ª copia)
File added: TEMP/NARF (5ª copia)
File added: TEMP/NERF (copia) (3ª copia)
File added: TEMP/NARF
File added: TEMP/NERF (copia) (copia)
File added: TEMP/NERF (8ª copia)
File added: TEMP/NERF (7ª copia)
File added: TEMP/NARF (copia)
File added: TEMP/NARF (otra copia)
File added: TEMP/NARF (4ª copia)
File added: TEMP/NERF
File added: TEMP/NARF (copia) (3ª copia)
ご覧のとおり、動作します。アーカイブも大丈夫です。これは、フォルダー全体を圧縮できる再帰関数です。唯一の問題は、空のフォルダーが作成されないことです。
乾杯。
以下は、ディレクトリ全体をzipファイルに圧縮するためのコードです。
これは、WindowsとLinuxの両方でZipファイルを作成しても問題ないようです。出力ファイルは、Windows(組み込みの圧縮フォルダー機能、WinZip、および7-Zip)およびlinuxで適切に抽出されるようです。ただし、Zipファイル内の空のディレクトリは厄介な問題のようです。以下の解決策は機能しているようですが、Linuxでの「zipinfo」の出力が懸念されます。また、Zipアーカイブ内の空のディレクトリに対してディレクトリのアクセス許可が正しく設定されていません。これには、さらに詳細な調査が必要と思われます。
this velocity review thread および this python mailing list thread から情報を得ました。
この関数は、親ディレクトリを持たないか、親ディレクトリを1つだけ持つZipアーカイブにファイルを配置するように設計されているため、Zipアーカイブパス内にファイルシステムパスの先頭のディレクトリは含まれません。これは一般に、ディレクトリを取得して、それを異なる場所に抽出できるZipファイルにしたい場合です。
キーワード引数:
dirPath-アーカイブするディレクトリへの文字列パス。これは唯一の必須引数です。絶対または相対のどちらでもかまいませんが、Zipアーカイブに含まれる先頭ディレクトリは1つまたは0個だけです。
zipFilePath-出力Zipファイルへの文字列パス。これは絶対パスでも相対パスでもかまいません。 Zipファイルが既に存在する場合、更新されます。そうでない場合は、作成されます。ゼロから置き換える場合は、この関数を呼び出す前に削除してください。 (デフォルトはdirPath + ".Zip"として計算されます)
includeDirInZip-最上位ディレクトリをアーカイブに含めるか省略するかを示すブール値。 (デフォルトはTrue)
(StackOverflowは、pythonを三重引用符付き文字列できれいに印刷できないため、ここでdoc文字列を投稿テキストに変換しました)
#!/usr/bin/python
import os
import zipfile
def zipdir(dirPath=None, zipFilePath=None, includeDirInZip=True):
if not zipFilePath:
zipFilePath = dirPath + ".Zip"
if not os.path.isdir(dirPath):
raise OSError("dirPath argument must point to a directory. "
"'%s' does not." % dirPath)
parentDir, dirToZip = os.path.split(dirPath)
#Little nested function to prepare the proper archive path
def trimPath(path):
archivePath = path.replace(parentDir, "", 1)
if parentDir:
archivePath = archivePath.replace(os.path.sep, "", 1)
if not includeDirInZip:
archivePath = archivePath.replace(dirToZip + os.path.sep, "", 1)
return os.path.normcase(archivePath)
outFile = zipfile.ZipFile(zipFilePath, "w",
compression=zipfile.Zip_DEFLATED)
for (archiveDirPath, dirNames, fileNames) in os.walk(dirPath):
for fileName in fileNames:
filePath = os.path.join(archiveDirPath, fileName)
outFile.write(filePath, trimPath(filePath))
#Make sure we get empty directories as well
if not fileNames and not dirNames:
zipInfo = zipfile.ZipInfo(trimPath(archiveDirPath) + "/")
#some web sites suggest doing
#zipInfo.external_attr = 16
#or
#zipInfo.external_attr = 48
#Here to allow for inserting an empty directory. Still TBD/TODO.
outFile.writestr(zipInfo, "")
outFile.close()
使用例は次のとおりです。 dirPath引数に複数の先行ディレクトリがある場合、デフォルトでは最後のディレクトリのみが含まれることに注意してください。 includeDirInZip = Falseを渡して、すべての先行ディレクトリを省略します。
zipdir("foo") #Just give it a dir and get a .Zip file
zipdir("foo", "foo2.Zip") #Get a .Zip file with a specific file name
zipdir("foo", "foo3nodir.Zip", False) #Omit the top level directory
zipdir("../test1/foo", "foo4nopardirs.Zip")
ここにフォルダを圧縮するために使用する私の機能があります:
import os
import os.path
import zipfile
def Zip_dir(dirpath, zippath):
fzip = zipfile.ZipFile(zippath, 'w', zipfile.Zip_DEFLATED)
basedir = os.path.dirname(dirpath) + '/'
for root, dirs, files in os.walk(dirpath):
if os.path.basename(root)[0] == '.':
continue #skip hidden directories
dirname = root.replace(basedir, '')
for f in files:
if f[-1] == '~' or (f[0] == '.' and f != '.htaccess'):
#skip backup files and all hidden files except .htaccess
continue
fzip.write(root + '/' + f, dirname + '/' + f)
fzip.close()
Info-Zipで作成されたZipファイルを見ると、ディレクトリが実際にリストされていることがわかります。
$ Zip foo.Zip -r foo
adding: foo/ (stored 0%)
adding: foo/foo.jpg (deflated 84%)
$ less foo.Zip
Archive: foo.Zip
Length Method Size Cmpr Date Time CRC-32 Name
-------- ------ ------- ---- ---------- ----- -------- ----
0 Stored 0 0% 2013-08-18 14:32 00000000 foo/
476320 Defl:N 77941 84% 2013-08-18 14:31 55a52268 foo/foo.jpg
-------- ------- --- -------
476320 77941 84% 2 files
ディレクトリエントリの長さはゼロであり、圧縮されていないことに注意してください。 Pythonを使用してディレクトリを名前で記述し、圧縮を使用しないように強制することで、同じことを達成できるようです。
if os.path.isdir(name):
zf.write(name, arcname=arcname, compress_type=zipfile.Zip_STORED)
else:
zf.write(name, arcname=arcname, compress_type=zipfile.Zip_DEFLATED)
arcname
が/
で終わることを確認する価値があるかもしれません。
インポートを追加した後、コードは正常に実行されます。スクリプトをどのように呼び出しますか。「..\packed\bin」ディレクトリのフォルダ構造を教えてください。
次の引数を使用してコードを呼び出しました。
planName='test.Zip'
files=['z.py',]
folders=['c:\\temp']
(success,filename)=createZipFile(planName,files,folders)
`
この便利な機能に感謝します!私も助けを探していたので、とても便利だと思いました。ただし、それを少し変更して、
basedir = os.path.dirname(dirpath) + '/'
だろう
basedir = os.path.dirname(dirpath + '/')
「C:\ folder\path\notWanted\to\Zip\Example」にあるフォルダー「Example」を圧縮したい場合、
私はWindowsに乗りました:
dirpath = 'C:\folder\path\notWanted\to\Zip\Example'
basedir = 'C:\folder\path\notWanted\to\Zip\Example/'
dirname = 'C:\folder\path\notWanted\to\Zip\Example\Example\Subfolder_etc'
しかし、私はあなたのコードが与えるべきだと思う
dirpath = 'C:\folder\path\notWanted\to\Zip\Example'
basedir = 'C:\folder\path\notWanted\to\Zip\Example\'
dirname = '\Subfolder_etc'
import os
import zipfile
zf = zipfile.ZipFile("file.Zip", "w")
for file in os.listdir(os.curdir):
if not file.endswith('.Zip') and os.path.isfile(os.curdir+'/'+file):
print file
zf.write(file)
Elif os.path.isdir(os.curdir+'/'+file):
print f
for f in os.listdir(os.curdir+'/'+file):
zf.write(file+'\\'+f)
zf.close()
私が実行した編集済みコードを示します。メーリングリストから取得した上記のコードに基づいています。インポートを追加し、メインルーチンを作成しました。また、コードを短くするために、出力ファイル名をいじるのを切り取りました。
#!/usr/bin/env python
import os, zipfile, glob, sys
def addFolderToZip(myZipFile,folder):
folder = folder.encode('ascii') #convert path to ascii for ZipFile Method
for file in glob.glob(folder+"/*"):
if os.path.isfile(file):
print file
myZipFile.write(file, os.path.basename(file), zipfile.Zip_DEFLATED)
Elif os.path.isdir(file):
addFolderToZip(myZipFile,file)
def createZipFile(filename,files,folders):
myZipFile = zipfile.ZipFile( filename, "w" ) # Open the Zip file for writing
for file in files:
file = file.encode('ascii') #convert path to ascii for ZipFile Method
if os.path.isfile(file):
(filepath, filename) = os.path.split(file)
myZipFile.write( file, filename, zipfile.Zip_DEFLATED )
for folder in folders:
addFolderToZip(myZipFile,folder)
myZipFile.close()
return (1,filename)
if __name__=="__main__":
#put everything in sys.argv[1] in out.Zip, skip files
print createZipFile("out.Zip", [], sys.argv[1])
職場では、私のWindowsボックスでは、このコードは正常に実行されましたが、zipファイルに「フォルダー」を作成しませんでした。少なくとも思い出した。今、自宅のLinuxボックスでは、作成されたZipファイルは不良のようです。
$ unzip -l out.Zip
Archive: out.Zip
End-of-central-directory signature not found. Either this file is not
a zipfile, or it constitutes one disk of a multi-part archive. In the
latter case the central directory and zipfile comment will be found on
the last disk(s) of this archive.
unzip: cannot find zipfile directory in one of out.Zip or
out.Zip.zip, and cannot find out.Zip.ZIP, period.
誤ってコードを壊したかどうかはわかりませんが、同じことだと思います。クロスプラットフォームの問題?いずれにせよ、それは私の元の質問とは関係ありません。 Zipファイル内のフォルダーを取得します。自分のコードの基になっているコードではなく、実際に実行したコードを投稿したかっただけです。