문제

다음 디렉토리 구조가 포함 된 zip 파일이 있습니다.

dir1\dir2\dir3a
dir1\dir2\dir3b

나는 그것을 압축하고 디렉토리 구조를 유지하려고하지만 오류가 발생합니다.

IOError: [Errno 2] No such file or directory: 'C:\\\projects\\\testFolder\\\subdir\\\unzip.exe'

테스트 폴더가 위의 DIR1이고 서브 디르는 DIR2입니다.

파일을 풀고 디렉토리 구조를 유지하는 빠른 방법이 있습니까?

도움이 되었습니까?

해결책

Python 2.6에있는 경우 추출 및 추출 방법이 좋습니다. 지금은 Python 2.5를 사용해야하므로 디렉토리가 존재하지 않으면 디렉토리를 만들면됩니다. 당신은 당신과 함께 디렉토리 목록을 얻을 수 있습니다 namelist() 방법. 디렉토리는 항상 전진 슬래시 (창에서도)로 끝납니다.

import os, zipfile

z = zipfile.ZipFile('myfile.zip')
for f in z.namelist():
    if f.endswith('/'):
        os.makedirs(f)

당신은 아마 그것을하고 싶지 않을 것입니다 바로 그거죠 그렇게 (예 : Namelist를 반복 할 때 Zip 파일의 내용을 추출하고 싶을 것입니다). 그러나 아이디어를 얻을 수 있습니다.

다른 팁

하지 않다 Trust Extract () 또는 ExtractAll ().

이 방법들은 파일을 파일 이름에 주어진 경로로 맹목적으로 추출합니다. 그러나 zip filename은“x /../../../ etc/passwd”와 같은 위험한 문자열을 포함하여 무엇이든 할 수 있습니다. 그러한 파일을 추출하면 전체 서버를 손상시킬 수있었습니다.

어쩌면 이것은 Python의 Zipfile 모듈에서보고 가능한 보안 구멍으로 간주되어야하지만, 수의 수많은 수용자는 과거에 똑같은 동작을 보여주었습니다. 폴더 구조가있는 zip 파일을 안전하게 비축하려면 각 파일 경로를 심층적으로 확인해야합니다.

나는 이것을 시도했고 그것을 재현 할 수있다. 다른 답변에 의해 제안 된 바와 같이 추출 방법은 ~ 아니다 문제를 풀다. 지퍼 파일이 어떻게 구조화되는지 오해하지 않는 한 이것은 지퍼 파일 모듈의 버그처럼 보입니다 (아마도 Windows 전용?).

testa\
testa\testb\
testa\testb\test.log
> test.zip

>>> from zipfile import ZipFile
>>> zipTest = ZipFile("C:\\...\\test.zip")
>>> zipTest.extractall("C:\\...\\")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "...\zipfile.py", line 940, in extractall
  File "...\zipfile.py", line 928, in extract
  File "...\zipfile.py", line 965, in _extract_member
IOError: [Errno 2] No such file or directory: 'C:\\...\\testa\\testb\\test.log'

내가한다면 printdir(), 나는 이것을 얻는다 (첫 번째 열) :

>>> zipTest.printdir()
File Name
testa/testb/
testa/testb/test.log

다음과 같은 첫 번째 항목 만 추출하려고하면 다음과 같습니다.

>>> zipTest.extract("testa/testb/")
'C:\\...\\testa\\testb'

디스크에서 폴더가 생성됩니다. testa, a 파일 testb 내부에. 이것이 분명히 추출을 시도하는 이유입니다. test.log 실패; testa\testb 폴더가 아닌 파일입니다.

#1 편집 : 파일 만 추출하면 작동합니다.

>>> zipTest.extract("testa/testb/test.log")
'C:\\...\\testa\\testb\\test.log'

편집 #2 : Jeff의 코드는 갈 길입니다. 반복 namelist; 디렉토리 인 경우 디렉토리를 작성하십시오. 그렇지 않으면 파일을 추출하십시오.

나는 이것을 말하는 것이 조금 늦었다는 것을 알고 있지만 Jeff가 옳다는 것을 알고 있습니다. 간단합니다.

import os
from zipfile import ZipFile as zip

def extractAll(zipName):
    z = zip(zipName)
    for f in z.namelist():
        if f.endswith('/'):
            os.makedirs(f)
        else:
            z.extract(f)

if __name__ == '__main__':
    zipList = ['one.zip', 'two.zip', 'three.zip']
    for zip in zipList:
        extractAll(zipName)

Python 2.6을 사용하는 경우 매우 쉬운 방법이 있습니다. ExtractAll 방법.

그러나 이후 zipfile 모듈은 C 확장없이 Python에서 완전히 구현되며 2.6 설치에서 복사하여 이전 버전의 Python과 함께 사용할 수 있습니다. 기능을 직접 상환하는 것보다 더 쉽게 찾을 수 있습니다. 그러나 함수 자체는 매우 짧습니다.

def extractall(self, path=None, members=None, pwd=None):
    """Extract all members from the archive to the current working
       directory. `path' specifies a different directory to extract to.
       `members' is optional and must be a subset of the list returned
       by namelist().
    """
    if members is None:
        members = self.namelist()

    for zipinfo in members:
        self.extract(zipinfo, path, pwd)

지퍼를 추출하기 위해 압축을 실행하려는 것처럼 들립니다.

파이썬을 사용하는 것이 좋습니다 zipfile 모듈, 따라서 파이썬에서 추출을 수행합니다.

import zipfile

def extract(zipfilepath, extractiondir):
    zip = zipfile.ZipFile(zipfilepath)
    zip.extractall(path=extractiondir)

폴더를 제외하기 위해 Namelist를 필터링하십시오

당신이해야 할 일은 namelist() 끝이 끝나는 항목 / 그리고 문제는 해결됩니다.

  z.extractall(dest, filter(lambda f: not f.endswith('/'), z.namelist()))

조이!

나와 같이, 당신은 오래된 파이썬 릴리스 (나의 경우, 2.4)와 함께 완전한 zip 아카이브를 추출해야한다.

import zipfile
import os

def unzip(source_file_path, destination_dir):
    destination_dir += '/'
    z = zipfile.ZipFile(source_file_path, 'r')
    for file in z.namelist():
        outfile_path = destination_dir + file
        if file.endswith('/'):
            os.makedirs(outfile_path)
        else:
            outfile = open(outfile_path, 'wb')
            outfile.write(z.read(file))
            outfile.close()
    z.close()

ZIP 파일에는 파일뿐만 아니라 디렉토리에 대한 항목이있을 수 있습니다. Archives를 만들 때 zip 명령, 전달 -D 아카이브에 디렉토리 항목 추가를 비활성화하는 옵션. 파이썬 2.6 일 때 ZipFile.extractall 메소드는 디렉토리 항목에서 실행되며 파일 그 자리에. 아카이브 항목이 반드시 순서대로 필요하지 않기 때문에 ZipFile.extractall 파일의 서브 디렉토리로 파일을 만들려고 할 때 자주 실패합니다. Python 모듈과 함께 사용하려는 아카이브가있는 경우 간단히 추출하여 -D 옵션. 여기에 정확히 그 일을하기 위해 한동안 사용해온 작은 스 니펫이 있습니다.

P=`pwd` && 
Z=`mktemp -d -t zip` && 
pushd $Z && 
unzip $P/<busted>.zip && 
zip -r -D $P/<new>.zip . && 
popd && 
rm -rf $Z

바꾸다 <busted>.zip 그리고 <new>.zip 현재 디렉토리와 관련된 실제 파일 이름으로. 그런 다음 모든 것을 복사하여 명령 쉘에 붙여 넣으면 Python 2.6으로 흔들릴 준비가 된 새 아카이브를 만듭니다. 거기 ~이다zip 압축을 풀지 않고이 디렉토리 항목을 제거하지만 IIRC는 다른 쉘 환경이나 지퍼 구성에서 이상하게 작동했습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top