압축 해제 된 tar의“--strip-components = 1”과 동일합니까?


48

tar.gz 파일을 지정된 하위 디렉토리 mysubfolder 로 추출하는 스크립트가 있습니다 .

mkdir mysubfolder; tar --extract --file=sourcefile.tar.gz --strip-components=1 --directory=mysubfolder;

zip 파일 로이 작업을 수행하는 동등한 방법이 있습니까?


2
그냥 bsdtar를 사용하십시오
— drizzt

답변:


26

Mathias가 말했듯 unzip이 그러한 옵션은 없지만 한 줄짜리 bash 스크립트가 작업을 수행 할 수 있습니다.

문제는 : 가장 좋은 방법은 아카이브 레이아웃에 따라 다릅니다. 컨텐츠가 아카이브 루트에 직접있는 경우 단일 최상위 디렉토리 를 가정 하는 솔루션은 비참하게 실패합니다 ( /a/foo /b/foo /foo탈피 /a와 의 혼돈에 대해 생각 하십시오 /b).

그리고 같은 실패가 발생합니다 tar --strip-component. 모든 규모에 맞는 솔루션은 없습니다.

그래서,이 가정의 루트 디렉토리를 제거 할 수 있습니다 하나의 (그리고 오직 하나) :

unzip -d "$dest" "$zip" && f=("$dest"/*) && mv "$dest"/*/* "$dest" && rmdir "${f[@]}"

그냥 확실히 두 번째 수준 파일 / DIRS 할 수 있도록 하지 (예를 들어, 최상위 부모의 같은 이름을 가진 /foo/foo). 그러나 /foo/bar/foo및 /foo/bar/bar확인합니다. 그들이하거나 안전하고 싶다면 추출을 위해 임시 디렉토리를 사용할 수 있습니다.

temp=$(mktemp -d) && unzip -d "$temp" "$zip" && mkdir -p "$dest" &&
mv "$temp"/*/* "$dest" && rmdir "$temp"/* "$temp"

Bash를 사용하는 경우 최상위 레벨이 단일 디렉토리인지 또는 다음을 사용하지 않는지 테스트 할 수 있습니다.

f=("$temp"/*); (( ${#f[@]} == 1 )) && [[ -d "${f[0]}" ]] && echo "Single dir!"

Bash에 관해서 dotglob는 숨겨진 파일을 포함하도록 켜야하며 모든 것을 하나의 편리한 기능으로 래핑 할 수 있습니다.

unzip-strip() (
    local zip=$1
    local dest=${2:-.}
    local temp=$(mktemp -d) && unzip -d "$temp" "$zip" && mkdir -p "$dest" &&
    shopt -s dotglob && local f=("$temp"/*) &&
    if (( ${#f[@]} == 1 )) && [[ -d "${f[0]}" ]] ; then
        mv "$temp"/*/* "$dest"
    else
        mv "$temp"/* "$dest"
    fi && rmdir "$temp"/* "$temp"
)

지금 당신의 ~/.bashrc또는 ~/.profile그것을 넣어 당신은 그것에 대해 다시 걱정할 필요가 없습니다. 간단히 다음과 같이 사용하십시오.

unzip-strip sourcefile.zip mysubfolder

( mysubfolder없는 경우 자동으로 생성됩니다 )


원하는대로 기존 디렉토리 구조로 압축을 풀지 않습니다 (mysubfolder 대신.을 사용하려고했습니다). 압축을 풀고 (zip-zip-with-top-dir.zip 압축) 복사 한 다음 (cp -rv extract-top-zip-dir / *) 복사했습니다.
— catgofire

4

에 대한 매뉴얼 페이지unzip 에서 이러한 옵션을 찾을 수 없으므로 이것이 불가능한 것 같습니다. :(

그러나 (상황에 따라) 해결할 수 있습니다. 예를 들어, zip 파일의 유일한 최상위 디렉토리 이름 foo-과 버전 번호 가 확실하다면 다음과 같이 할 수 있습니다.

cd /tmp
unzip /path/to/file.zip
cd foo-*
cp -r . /path/to/destination/folder

좋은 접근 방법이지만 약간 불완전합니다. 완전히 추출 된 내용이있는 foo * dir이 있습니다.
— MestreLion

예, rm -rf foo-*잠재적으로 위험하므로 의도적으로 추가하지 않았습니다 . 이미 이름이 지정된 폴더가 있다면 어떻게 foo-bar합니까? 추출은 /tmp폴더 내에서 수행되며 , 매번 자동으로 비워집니다.
— Mathias Bynens

그렇기 때문에 &&주어진 단계는 이전 단계가 성공한 경우에만 발생하므로 마지막 단계 ( rm)는 모든 단계가 오류없이 완료된 경우에만 실행됩니다 .
— MestreLion

2
그렇기 때문에 /tmp/some-hardcoded-folder-name임시 폴더로 사용자 를 사용해서는 안되며 대신 mktemp기존 폴더를 사용하지 않아야합니다. 아래에서 내 대답을 확인하십시오.
— MestreLion

1

-j경로를 정크로 만드는 데 사용할 수 있습니다 (디렉토리를 만들지 마십시오). 이것은 다소 일반적인 단일 레벨 아카이브에만 권장됩니다. 여러 수준의 디렉토리 구조를 가진 아카이브는 평평해질 것입니다. 이로 인해 파일을 추출 할 때 이름이 충돌 할 수도 있습니다.

압축 해제 매뉴얼 페이지에서 :

   -j     junk  paths.   The  archive's directory structure is not recreated; all files are deposited in the
          extraction directory (by default, the current one).
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.