2008-09-20 2 views
43

unzip 명령에는 아카이브를 재귀 적으로 압축 해제하는 옵션이 없습니다.Unix 명령 줄에서 디렉토리와 그 하위 디렉토리의 아카이브를 재귀 적으로 압축 해제합니까?

만약 내가 다음 디렉토리 구조 및 아카이브가 :

 
/Mother/Loving.zip 
/Scurvy/Sea Dogs.zip 
/Scurvy/Cures/Limes.zip 

을 그리고 각 아카이브와 같은 이름을 가진 디렉토리에 아카이브의 모든 압축을 풀 :

 
/Mother/Loving/1.txt 
/Mother/Loving.zip 
/Scurvy/Sea Dogs/2.txt 
/Scurvy/Sea Dogs.zip 
/Scurvy/Cures/Limes/3.txt 
/Scurvy/Cures/Limes.zip 

어떤 명령이나 명령을 내릴 수 있습니까?

공백이있는 파일 이름에 영향을주지 않는 것이 중요합니다. -r 플래그를 사용하여 gunzip으로 같은

find . -name "*.zip" | while read filename; do unzip -o -d "`basename -s .zip "$filename"`" "$filename"; done; 
+0

260자를 초과하는 긴 파일 경로는 어떻게됩니까? https://superuser.com/a/1263234/439537 – Andrew

답변

59

당신이 각각의 폴더에 파일을 추출 할 경우 높은 처리 할 수있는 시스템이

find . -name "*.zip" | while read filename; do unzip -o -d "`dirname "$filename"`" "$filename"; done; 

다중 처리 버전의 I/O 시도 할 수 있습니다 :

find . -name "*.zip" | xargs -P 5 -I fileName sh -c 'unzip -o -d "$(dirname "fileName")/$(basename -s .zip "fileName")" "fileName"' 
+1

전체 디렉토리를 보존하기 때문에 올바른 방법입니다. 구조! – kynan

+2

__NOTE__ - 요청한대로 아카이브와 이름이 같은 디렉토리에 파일을 추출하지 않습니다. – emlai

+0

xargs에 멀티 코어가 지원되지 않습니다. – chuckrector

29

다음은 find 명령과 while 루프를 포함 한 솔루션입니다. 명령 줄에 지정된 파일 이름 중 하나라도 디렉토리 인 경우 gzip은 디렉토리로 내려 가서 찾은 모든 파일을 압축합니다 (또는 gunzip의 경우 압축을 푸십시오).

은, 구문은 기본 이름에 대한 약간 다른

http://www.computerhope.com/unix/gzip.htm

+3

** 참고 ** - 모든 압축 파일을 ** 작업 디렉토리 ** 상대방의 압축을 요청한 동안 **. [Vivek의 대답] (http://stackoverflow.com/a/2318189/3191896)을 참조하십시오. –

+0

흠, AFAICT 작업 디렉토리에 모두 압축을 풀지 않은 것으로 보입니다. OS X El Capitan 10.11.6에서 Unzip 5.52를 사용하고 있습니다. 결과는 Vivek 's와 동일하게 보입니다. 그의 답변을 수락, 그것은 또한 여러 코어를 활용하는 방법을 보여주기 때문에! – chuckrector

2

뭔가 ....

여행 디렉토리 구조를 재귀 적 :

+2

그는 gzip 파일이 아니라 zip 파일에 대해 특별히 이야기하고 있습니다. – dvorak

4

당신은

find . -name "*.zip" -exec unzip {} \; 
+0

이렇게하면 각 하위 디렉토리를 기준으로하지 않고 모든 항목을 현재 디렉토리로 압축 해제합니다. 또한 각 아카이브와 동일한 이름의 디렉토리로 압축을 풀지 않습니다. – chuckrector

+0

-d 권한을 얻는 것이 독자의 연습 문제로 남아 있다고 가정합니다. 그 독자는 명령에서 {}를 사용하는 것이 허용된다는 것을 알아야합니다. sh를 호출하고 {}를 변수에 할당하여이 문제를 해결하십시오. –

+0

-execdir은 때때로 -exec보다 바람직합니다. 이 경우 나는 그것이 중요 할 것이라고 생각하지 않는다. –

0

당신이 Cygwin에서 사용하는 경우 작업을 수행하는 단일 명령 줄에서 간부 플래그와 함께 찾아 사용할 수 있습니다 명령.

find . -name "*.zip" | while read filename; do unzip -o -d "`basename "$filename" .zip`" "$filename"; done; 
0

나는 이것이 아주 오래되었다는 것을 알았지 만 비슷한 솔루션에 대한 Google의 첫 번째 히트 곡 중 하나이기 때문에 여기에서 내가 한 일을 게시 할 것입니다. 내 시나리오는 내가 기본적으로 그냥 완전히 포함 된 모든 항아리와 함께 항아리를 폭발 원하는대로 약간 다른, 그래서 나는 다음과 같은 bash는 기능 썼다 :

function explode { 
    local target="$1" 
    echo "Exploding $target." 
    if [ -f "$target" ] ; then 
     explodeFile "$target" 
    elif [ -d "$target" ] ; then 
     while [ "$(find "$target" -type f -regextype posix-egrep -iregex ".*\.(zip|jar|ear|war|sar)")" != "" ] ; do 
      find "$target" -type f -regextype posix-egrep -iregex ".*\.(zip|jar|ear|war|sar)" -exec bash -c 'source "<file-where-this-function-is-stored>" ; explode "{}"' \; 
     done 
    else 
     echo "Could not find $target." 
    fi 
} 

function explodeFile { 
    local target="$1" 
    echo "Exploding file $target." 
    mv "$target" "$target.tmp" 
    unzip -q "$target.tmp" -d "$target" 
    rm "$target.tmp" 
} 

주 당신이 저장하는 경우 필요한 <file-where-this-function-is-stored>을 이 파일은 비대륙 형 쉘로 읽지 않은 파일입니다. 함수를 비대화 형 쉘에로드 된 파일 (예 : .bashrc)에 저장하는 경우 전체 source 문을 삭제할 수 있습니다. 바라기를 이것은 누군가를 도울 것입니다.

약간의 경고 - explodeFile도 ziped 파일을 삭제합니다. 물론 마지막 줄을 주석 처리하여 변경할 수 있습니다.

10

올바르게 바로 제거 확장자 (줄 바꿈 포함) 모든 파일 이름을 처리하고 파일과 같은 위치에있는 디렉토리로 추출 해결책 :

find . -name '*.zip' -exec sh -c 'unzip -o -d "${0%.*}" "$0"' '{}' ';' 

참고하면 쉽게 만들 수 있습니다

find . '(' -name '*.zip' -o -name '*.jar' ')' -exec ... 
0

또 다른 흥미로운 솔루션은 다음과 같습니다 :

는 예를 들면, -o 사용하여 추가하여 더 많은 파일 형식 (예 : .jar 등)를 처리 0
DESTINY=[Give the output that you intend] 

# Don't forget to change from .ZIP to .zip. 
# In my case the files were in .ZIP. 
# The echo were for debug purpose. 

find . -name "*.ZIP" | while read filename; do 
ADDRESS=$filename 
#echo "Address: $ADDRESS" 
BASENAME=`basename $filename .ZIP` 
#echo "Basename: $BASENAME" 
unzip -d "$DESTINY$BASENAME" "$ADDRESS"; 
done; 
관련 문제