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


39

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

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


이것은 가능 해야하는 것처럼 보였지만 zip에 단일 파일 만 포함되어 있으면 zip을 추출하여 다른 명령으로 파일을 파이프하는 것이 가능한 것처럼 보입니다. 다중 파일 zip에서 특정 파일을 추출하고 싶었습니다. 파이핑 대신 여러 명령을 연결하는 것으로 전환했습니다. 필요한 것.
Stan Kurdziel

pigz를 확인하십시오. 파이프로 사용합니다. andrew.tumblr.com/post/2316602611
dmourati

답변:


22

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

1
당신과 파이썬 락 !!!
Farid Nouri Neshat

3
좋은 한 줄짜리 파일과 파일이 메모리에 맞아야한다고 언급 한 +1. (불행히도 파일 형식 구조로 인해 pkzip 파일의 압축을 풀 수있는 방법은 없습니다).
lxgr 2016 년

2
이것은 추출하기 전에 메모리의 모든 것을 버퍼링한다는 것을 명심하십시오
William Casarin

1
파일을 메모리에 쉽게 넣을 수 있다면 스트림으로 읽을 수없는 이유 가 없습니다. 정확하지 않습니다. 컨텐츠를 추출하기 전에 전체 zip 아카이브를 메모리에 버퍼링해야하는 이유는 스트림으로 읽을 수 없기 때문입니다. 물론 zip 아카이브를 파일에 쓰지 않는 것이 여전히 유용 할 수 있습니다.
Håkan Lindqvist 2016 년

이것은 스트림 이 아니며 , .read()방법 을 사용하여 메모리의 전체 파일을 읽는 중입니다.
Romuald Brunet

17

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

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

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

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


zip에 여러 파일이 들어 있으면 -p는 파일 이름을 매개 변수로 사용하여 단일 파일을 인쇄 할 수 있습니다. unzip -p temp.zip file-inside-zip
Taavi Ilves

7

당신이하고 싶은 일은 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가 필요하지 않다고 생각합니다.


그냥 의견; 어떤 사람들은 압축 해제 옵션으로 파이썬이나 다른 언어를 원합니다. 대표적인 예는 시스템에 tar 또는 unzip을 포함하지 않는 Heroku입니다. 해결 방법은 허용되는 Java를 설치하여 jar을 사용하는 것입니다.
Nick

이 답변에는 funzip 및 이와 유사한 도구 (특히 아카이브의 첫 번째 멤버 만 표시 할 수있는 기능)의 제한 사항에 대한 자세한 내용이 있습니다. unix.stackexchange.com/a/211286/77539
Joshua Goldberg

6

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

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

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


여러 파일에서도 잘 작동합니다
jonnor

5

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

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

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

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

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

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

4

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

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

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


4

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

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

3

이 작업을 수행 할 수있는 가장 간단한 공통 유틸리티 jar는입니다. 파일 인수를 전달하지 않으면 STDIN이 사용되는 것으로 간주됩니다. 또한 작업을위한 tar프로그램 과 유사한 인수가 필요합니다.

예를 들어 아카이브의 내용을 나열

curl https://my.example.com/file.zip | jar t

Java가 항상 설치되는 것은 아니지만 해당 시스템에 Java가 항상 jar가장 편리한 방법입니다.


3

내 대답다시 게시 :

BusyBox unzip는 stdin을 가지고 모든 파일을 추출 할 수 있습니다.

wget -qO- http://downloads.wordpress.org/plugin/akismet.2.5.3.zip | busybox unzip -

대시 unzip는 stdin을 입력으로 사용하는 것입니다.

당신은 할 수 있습니다

cat file.zip | busybox unzip -

그러나 그것은 단지 중복입니다 unzip file.zip.

배포판에서 기본적으로 BusyBox를 사용하는 경우 (예 : 알파인)을 실행하십시오 unzip -.


1

실제로 좀 더 복잡한 것이 필요했습니다. 특정 파일이 있으면 추출하십시오. 어려움은 입력 파일 스트림이 zip 파일이 아니기 때문에 파이프를 계속 통과해야한다는 것입니다. 여기 내 솔루션이 있습니다 (주로 Jason R. Coombs 솔루션 덕분에)

python -c "import zipfile,sys,StringIO
data=sys.stdin.read()
try:
    z=zipfile.ZipFile(StringIO.StringIO(data))
    z.open(\"$1\")
    sys.stdout.write(z.read(\"$1\"))
except (RuntimeError, zipfile.BadZipfile):
    sys.stdout.write(data)"

이 파일을 내 컴퓨터의 "/ bin"폴더에 "effpoptp"(단순 이름 아님)이라는 파일로 저장 했으므로 테스트하는 방법은 다음과 같습니다.

cat defaultModel.mwb|effpoptp "document.mwb.xml"

목적은 MySQL Workbench 파일을 버전 제어하는 ​​것입니다. 여기서 파일은 워크 벤치 파일로 이름 지정된 xml 파일 또는 전체 워크 벤치 파일 일 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.