파이프를 통해 비행하는 파일 압축 해제 상황은 압축

압축 해제 또는 유사한 프로그램을 표준 출력에서 ​​작동시킬 수 있습니까? 상황은 압축 파일을 다운로드하는 중이며 압축이 풀린 상태입니다.

관련 문제 : 다운로드 한 파일을 bash의 표준 출력으로 파이프하려면 어떻게해야합니까?



답변

zip 파일은 실제로 컨테이너 형식이지만 파일이 메모리에 쉽게 들어갈 수있는 경우 파이프 (stdin)에서 읽을 수없는 이유는 없습니다. 다음은 zip 파일을 표준 입력으로 가져 와서 현재 디렉토리 또는 지정된 경우 지정된 디렉토리로 컨텐츠를 추출하는 Python 스크립트입니다.

import zipfile
import sys
import StringIO
data = StringIO.StringIO(sys.stdin.read())
z = zipfile.ZipFile(data)
dest = sys.argv[1] if len(sys.argv) == 2 else '.'
z.extractall(dest)

이 스크립트는 한 줄로 축소하여 별칭으로 만들 수 있습니다.

alias unzip-stdin="python -c \"import zipfile,sys,StringIO;zipfile.ZipFile(StringIO.StringIO(sys.stdin.read())).extractall(sys.argv[1] if len(sys.argv) == 2 else '.')\""

이제 wget의 출력을 쉽게 압축 해제하십시오.

wget http://your.domain.com/your/file.zip -O - | unzip-stdin target_dir


답변

이것은 예상대로 작동하지 않을 것입니다. Zip은 압축 형식 일뿐만 아니라 컨테이너 형식이기도합니다. tar 및 gzip.bzip2 작업을 하나로 롤업합니다. zip에 단일 파일이 있으면 unzip -p를 사용하여 파일을 stdout으로 추출 할 수 있습니다. 파일이 둘 이상인 경우 파일의 시작 및 중지 위치를 알 수있는 방법이 없습니다.

stdin에서 읽을 때 unzip 매뉴얼 페이지에는 다음 문장이 있습니다.

funzip을 제외하고 표준 입력에서 읽은 아카이브는 아직 지원되지 않습니다 (그리고 아카이브의 첫 번째 멤버 만 추출 할 수 있음).

funzip으로 운이 좋을 수도 있습니다.


답변

당신이하고 싶은 일은 unzip인수가 아닌 표준 입력으로 ZIP 파일을 가져 오는 것입니다. 이것은 일반적으로 사용하여 쉽게 지원 gziptar현물과 도구의 -인수입니다. 그러나 표준 unzip은 그렇게하지 않습니다 (물론 파이프로의 추출을 지원합니다). 그러나 모든 것이 손실되지는 않습니다 …

funzip 매뉴얼 페이지.

파일 인수가없는 funzip은 필터 역할을합니다. 즉, ZIP 아카이브 (또는 gzip 파일)가 표준 입력으로 파이프되고 있다고 가정하고 아카이브에서 stdout으로 첫 번째 멤버를 추출합니다. stdin이 tty 장치에서 오는 경우 funzip은이 데이터가 (이진) 압축 데이터 스트림 일 수 없다고 가정하고 대신 짧은 도움말 텍스트를 표시합니다. 파일 인수가 있으면 stdin 대신 지정된 파일에서 입력을 읽습니다.

단일 구성원 추출에 대한 제한을 감안할 때 funzip은 tar (1)와 같은 보조 아카이버 프로그램과 함께 사용하면 가장 유용합니다. 다음 섹션에는 테이프에 디스크 백업의 경우이 사용법을 보여주는 예가 포함되어 있습니다.

이것은 대부분의 리눅스 아카이브가 일반적으로 TAR되고 어떤 식 으로든 압축된다는 생각과 잘 어울립니다 (gzip, bzip 등). 당신이있는 경우에 당신을 위해 일할 것 tar.ZIP입니다.


funzipInfo-ZIP의 원저자 인 Mark Adler가 작성한 것은 주목할 가치가 있습니다. 그는 funzip 맨 페이지에 글을 쓰고

this functionality should be incorporated into unzip itself (future release).

그러나 그러한 업데이트는 보이지 않습니다. 다른 보관 방법이 TAR에서 쉽게 작동했기 때문에 Mark가 필요하지 않다고 생각합니다.


답변

curl이 기본적으로 설치되어 있기 때문에 curl을 사용하고 싶습니다 ( -L종종 발생하는 리디렉션에 필요함).

curl -L http://example.com/file.zip | bsdtar -xvf - -C /path/to/directory/

그러나 bsdtar기본적으로 설치되어 있지 않아서 funzip일할 수 없었습니다 .


답변

이것은 비슷한 질문에 대한 나의 대답 을 다시 게시 한 것입니다 .

ZIP 파일 형식은 아카이브 끝에 디렉토리 (인덱스)를 포함합니다. 이 디렉토리는 아카이브 내에서 각 파일의 위치를 ​​알려주므로 전체 아카이브를 읽지 않고도 신속하고 무작위로 액세스 할 수 있습니다.

이것은 파이프를 통해 ZIP 아카이브를 읽으려고 할 때 문제가있는 것으로 보입니다. 인덱스는 끝까지 액세스 할 수 없으므로 파일을 완전히 읽은 후 더 이상 사용할 수 없을 때까지 개별 멤버를 올바르게 추출 할 수 없습니다. . 따라서 아카이브를 파이프를 통해 공급할 때 대부분의 ZIP 압축 풀기 프로그램이 실패하는 것은 놀라운 일이 아닙니다.

아카이브의 끝에있는 디렉토리는 파일 메타 정보가 아카이브에 저장되는 유일한 위치 는 아닙니다 . 또한 개별 항목은 중복을 위해이 정보를 로컬 파일 헤더에 포함합니다.

모든 ZIP 압축 풀기 프로그램이 색인을 사용할 수 없을 때 로컬 파일 헤더를 사용하는 것은 아니지만 tar 및 cpio 프론트 엔드는 libarchive (일명 bsdtar 및 bsdcpio) 로 파이프를 읽을 때 수행 할 수 있으며 그렇게 할 것입니다 .

wget -qO- http://example.org/file.zip | bsdtar -xvf-


답변

가장 일반적인 OSS 구현 인 Info-Zip으로는 불가능합니다. 더 중요한 것은 ZIP 아카이브의 구성으로 인해 권장되지 않습니다.

형식 변경이 가능한 경우 tar (1)를 대신 사용하십시오. 스트리밍 된 입력 / 출력에 매우 만족하며 실제로 기본적으로이를 예상합니다.

또한 파일 이름으로 “-“를 지정하여 응용 프로그램에서 스트림 입력 / 출력을 기대하는지 여부를 알 수 있습니다. Info-Zip은 당신이 상상할 수 있듯이 이것을 유효한 주장으로 취급하지 않습니다.


답변

zsh에서는 다음을 수행 할 수 있습니다.

unzip =( curl http://example.com/someZipFile.zip )