"압축 해제"가 미리 단일 폴더를 생성하는지 어떻게 알 수 있나요?

"압축 해제"가 미리 단일 폴더를 생성하는지 어떻게 알 수 있나요?

일반적인 상황은 다른 작업이 포함된 디렉터리에 zip 파일을 포함하는 것입니다.

me@work ~/my_working_folder $ ls
downloaded.zip  workfile1  workfile2  workfile3

압축을 풀고 싶지만 downloaded.zip혼란을 야기할 것인지, 아니면 자체 디렉토리를 멋지게 생성할 것인지 모르겠습니다. 제가 작업 중인 해결 방법은 임시 폴더를 만들고 해당 폴더에 압축을 푸는 것입니다.

me@work ~/my_working_folder $ mkdir temp && cp downloaded.zip temp && cd temp
me@work ~/my_working_folder/temp $ ls
downloaded.zip
me@work ~/my_working_folder/temp $ unzip downloaded.zip 
Archive:  downloaded.zip
   creating: nice_folder/

이렇게 하면 my_working_folderzip 파일이 많은 양의 콘텐츠로 채워지는 것을 방지할 수 있습니다.

내 질문은 다음과 같습니다압축을 풀기 전에 zip 파일에 폴더가 하나만 포함되어 있는지 확인하는 더 좋은 방법이 있습니까?

답변1

알았어 너할 수 있다무조건 하위 디렉터리로 추출한 다음 단일 항목만 포함하게 되면 삭제하세요.

그런데 왜 가?건전하고 간단한 솔루션(의지하다이르카초), 언제부터 사용할 수 있나요 awk? :)

sunzip ()
{
    if [ $# -ne 1 ] || ! [ -f "$1" ]
    then
        printf '%s\n' "Expected a filename as the first (and only) argument. Aborting."
        return 1
    fi

    extract_dir="."

    # Strip the leading and trailing information about the zip file (leaving
    # only the lines with filenames), then check to make sure *all* filenames
    # contain a /.
    # If any file doesn't contain a / (i.e. is not located in a directory or is
    # a directory itself), exit with a failure code to trigger creating a new
    # directory for the extraction.
    if ! unzip -l "$1" | tail -n +4 | head -n -2 | awk 'BEGIN {lastprefix = ""} {if (match($4, /[^/]+/)) {prefix=substr($4, RSTART, RLENGTH); if (lastprefix != "" && prefix != lastprefix) {exit 1}; lastprefix=prefix}}'
    then
        extract_dir="${1%.zip}"
    fi

    unzip -d "$extract_dir" "$1"
}

빠르고 더러운. InfoZIP unzipv6.0에 적용됩니다. 추가 매개변수를 허용하거나 자동으로 사용 하거나 추출 하위 디렉터리에 다른 이름(현재 파일 이름으로 결정됨 ) 을 사용하는
등 필요에 따라 이를 조정할 수 있습니다 .unzipzip


아, 방금 이 해결 방법이 가장 일반적인 두 가지 경우(1. ZIP 파일에 콘텐츠가 있는 디렉터리가 포함되어 있는 경우, 2. ZIP 파일에 여러 개의 별도 파일 및/또는 디렉터리가 포함된 경우)를 올바르게 처리하지만 루트 디렉터리가 생성되지 않는 것을 확인했습니다. ZIP 파일에는 여러 디렉터리가 포함되어 있지만 파일은 없습니다. 하위 디렉터리는...

편집하다:안정적인. 이제 스크립트 awk는 ZIP 파일에 포함된 각 경로의 첫 번째 구성 요소("접두사")를 저장하고 이전 접두사와 다른 접두사가 감지되면 즉시 중단됩니다. 이는 모든 내용이 동일한 하위 디렉터리에 포함된 ZIP 파일을 무시하면서 여러 파일과 여러 디렉터리(둘 다 이름이 다르기 때문에)를 캡처합니다.

답변2

추출하기 전에 아카이브 내용을 확인하는 대신 다음 명령을 사용하여 추출할 수도 있습니다.unar이는 원하는 동작을 제공합니다. 기본적으로 아카이브에 단일 최상위 디렉토리가 포함되어 있으면 unar있는 그대로 추출되고, 그렇지 않으면 아카이브 이름을 딴 디렉토리를 생성하여 거기에서 추출합니다. 이 옵션을 사용하면 모든 경우에 디렉터리를 강제로 생성할 수 있습니다 -d.

unar또한 다양한 아카이브 형식을 지원한다는 장점도 있습니다.

답변3

설명서에서...

[-d 디렉토리]

파일을 추출할 선택적 디렉터리입니다. 기본적으로 모든 파일과 하위 디렉터리는 현재 디렉터리에 다시 생성됩니다. -d 옵션을 사용하면 임의 디렉터리에서 추출할 수 있습니다(해당 디렉터리에 대한 쓰기 권한은 항상 가정됩니다). 이 옵션은 명령줄 끝에 나타날 필요가 없습니다. zipfile 지정 앞(일반 옵션 사용), zipfile 지정 바로 뒤 또는 파일과 -x 옵션 사이에도 허용될 수 있습니다. 옵션과 디렉토리는 사이에 공백 없이 연결될 수 있지만 이로 인해 정상적인 쉘 동작이 억제될 수 있다는 점에 유의하십시오. 특히 -d ~(물결표)는 Unix C 셸에서 사용자의 홈 디렉터리 이름으로 확장되지만 현재 디렉터리의 문자 그대로 하위 디렉터리 -d~로 처리됩니다 .~

그래서...

unzip -d new_dir zipfile.zip

그러면 new_dir 디렉토리가 생성되고 그 안에 있는 아카이브가 추출되므로 먼저 살펴보지 않고도 매번 잠재적인 혼란을 피할 수 있습니다. 살펴보는 것도 유용합니다 man unzip.매뉴얼 페이지에 대한 추가 도움말.

답변4

기본 압축 해제를 사용하는 멋진 bash one 라이너는 다음과 같습니다.

 while read -r line; do (unzip -d "$(basename "$line" .zip)" "$line"); done < <(find . | grep '.zip')

추출할 zip 파일이 포함된 디렉터리에서 이 명령을 실행하세요.

  • < <결과를 find . | grep '.zip'루프 에 입력합니다 while.
  • 반환된 파일 이름은 다음 find과 같이 저장 됩니다.line
  • while루프는 파일 이름을 반복하여 파일 line이름을do
  • 그러면 다음의 파일 이름을 사용하여 do디렉터리가 생성 됩니다.basename$line
    • 확장자는 .zip문자열에서 제거할 텍스트로 지정됩니다.
    • 확장자 없이 파일 이름만 남습니다(기본 이름!)
  • 새 디렉터리를 만드는 데 -d사용할 기본 이름을 인수합니다..zip
    • /folder/archive.zip그러면 기다리게 됩니다 /folder/archive/unzipped_file.txt.
    • 이는 Windows/7zip의 "추출 대상" 옵션과 매우 유사합니다.
  • 그런 다음 이 변수는 $line압축 해제 대상으로 사용됩니다.

이 라이너는 다양한 아이템에도 사용할 수 있어요! 파일 이동, 파일 압축, 파일 복사... 검색이 재귀적이어서 매우 편리합니다!

관련 정보