확장자만 알려진 zip 파일에서 단일 파일 추출

확장자만 알려진 zip 파일에서 단일 파일 추출

내 요구 사항의 첫 번째 부분:

나는 그것에서 단일 파일을 추출하고 싶습니다 ex1234.zip. 구조 및 내용 ex1234.zip:

ex1234 (directory)
    directory1
    ex1234 (directory)
    directory2
    ex1234.csv

파일 만 추출하고 싶지만 ex1234.csv이름을 모릅니다.

두 번째 부분은 exXXXX.zip동일한 디렉터리의 모든 항목에 대해 이 작업을 수행할 수 있다는 것입니다.

ex1234.zip
ex3245.zip
ex8829.zip
exXXXX.zip…

출력은 다음과 같습니다:

ex1234.csv
ex3245.csv
ex8829.csv
exXXXX.csv

실제 샘플:

$ 덜CW2178470.zip
아카이브: CW2178470.zip
Zip 파일 크기: 26108바이트, 항목 수: 26
-rw---- 2.0 fat 108 bl defN 2004년 8월 15일 09:37 CW2178470/CW2178470.csv
-rw---- 2.0 fat 1363 bl defN 15-Aug-04 09:37 CW2178470/config/BusinessContactApprovers.csv
-rw---- 2.0 fat 158 ​​​​bl defN 2004년 8월 15일 09:37 CW2178470/CW2178470/announcements.xml
-rw---- 2.0 fat 1037 bl defN 2004년 8월 15일 09:37 CW2178470/CW2178470/Plan/plan.xml
-rw---- 2.0 fat 141 bl defN 2004년 8월 15일 09:37 CW2178470/CW2178470/Plan/tasks.xml
-rw---- 2.0 fat 2408 bl defN 2004년 8월 15일 09:37 CW2178470/CW2178470/FI_Doc208411460_doc.xml
-rw---- 2.0 fat 215 bl defN 2004년 8월 15일 09:37 CW2178470/CW2178470/MessageBoard/nb_27482kst.26ihyzj_.htm
-rw---- 2.0 fat 2364 bl defN 2004년 8월 15일 09:37 CW2178470/CW2178470/MessageBoard/messageboard.xml
-rw---- 2.0 fat 1250 bl defN 2004년 8월 15일 09:37 CW2178470/CW2178470/team.xml
-rw---- 2.0 fat 22016 bl defN 2004년 8월 15일 09:37 CW2178470/CW2178470/Doc208411460.doc
-rw---- 2.0 fat 9973 bl defN 2004년 8월 15일 09:37 CW2178470/CW2178470/audistory.xml
-rw---- 2.0 fat 6731 bl defN 2004년 8월 15일 09:37 CW2178470/CW2178470/ws.xml
-rw---- 2.0 fat 308 bl defN 2004년 8월 15일 09:37 CW2178470/xsd/WSFolder.xsd
-rw---- 2.0 fat 4897 bl defN 2004년 8월 15일 09:37 CW2178470/xsd/Task.xsd
-rw---- 2.0 fat 770 bl defN 2004년 8월 15일 09:37 CW2178470/xsd/ContractWorkspace.xsd
-rw---- 2.0 fat 4754 bl defN 2004년 8월 15일 09:37 CW2178470/xsd/AuditHistory.xsd
-rw---- 2.0 fat 25564 bl defN 2004년 8월 15일 09:37 CW2178470/xsd/CommonTypes.xsd
-rw---- 2.0 fat 5657 bl defN 2004년 8월 15일 09:37 CW2178470/xsd/MessageBoard.xsd
-rw---- 2.0 fat 2471 bl defN 2004년 8월 15일 09:37 CW2178470/xsd/Plan.xsd
-rw---- 2.0 fat 337 bl defN 2004년 8월 15일 09:37 CW2178470/xsd/InternalContractWorkspace.xsd
-rw---- 2.0 fat 1045 bl defN 2004년 8월 15일 09:37 CW2178470/xsd/SalesContractRequest.xsd
-rw---- 2.0 fat 3133 bl defN 2004년 8월 15일 09:37 CW2178470/xsd/FolderItem.xsd
-rw---- 2.0 fat 906 bl defN 2004년 8월 15일 09:37 CW2178470/xsd/ContractRequest.xsd
-rw---- 2.0 fat 8973 bl defN 2004년 8월 15일 09:37 CW2178470/xsd/WorkspaceTypes.xsd
-rw---- 2.0 fat 4645 bl defN 2004년 8월 15일 09:37 CW2178470/xsd/Team.xsd
-rw---- 2.0 fat 781 bl defN 2004년 8월 15일 09:37 CW2178470/xsd/SalesContractWorkspace.xsd
26개 파일, 112005바이트 비압축, 21940바이트 압축: 80.4%
(끝)

답변1

다음과 같이 사용할 수 있습니다 unzip.

unzip -j file[.zip] [file] [-x xfile]

여기서 는 -j휴지통 경로를 나타내고, file[.zip]는 아카이브 이름, [file]는 처리할 아카이브 멤버, [-x xfile]는 처리에서 제외할 아카이브 멤버 목록입니다. 이러한 모든 옵션은 매뉴얼 페이지에 자세히 설명되어 있습니다.
따라서 귀하의 경우에는 다음과 같이 실행하십시오.

unzip -j ex1234.zip '*/*.csv' -x '*/*/*'

*.csv깊이 수준 2와 일치하는 아카이브의 모든 파일은 현재 디렉터리에서 추출됩니다 ( 경로가 최소 2개 이상 일치하므로 ex1234.zip깊이 수준 3 이하의 아카이브 구성원 제외 ).'*/*/*'/

이제 현재 디렉터리의 모든 아카이브를 처리하려면 다음을 실행할 수 있습니다.

for zipfile in *.zip; do unzip -j "$zipfile" '*/*.csv' -x '*/*/*'; done

.csv현재 디렉터리의 모든 아카이브에서 파일을 추출합니다(그래서 -j필요한 것입니다).
특정 경우에는 레벨 1 깊이가 없으므로 .csv다음을 실행할 수도 있습니다.

for zipfile in *.zip; do unzip -j "$zipfile" '*.csv' -x '*/*/*'; done

이렇게 하면 동일한 결과가 생성됩니다.
실행을 테스트하고 실제로 추출하지 않고 어떤 파일(아카이브 경로)이 추출되는지 확인하려면 다음 -j으로 바꾸십시오 -qql.

for zipfile in *.zip; do unzip -qql "$zipfile" '*/*.csv' -x '*/*/*'; done

참고로 이 -j옵션은 생략 가능만약에 그리고 만약에추출할 파일은 .csv깊이 수준 1에 있습니다(즉, 상위 디렉터리가 없음). 이 경우 간단히 다음을 실행할 수 있습니다.

for zipfile in *.zip; do unzip "$zipfile" '*.csv' -x '*/*'; done

답변2

데비안에서 제공하는 압축 해제를 사용해 보세요:

UnZip 6.00 of 20 April 2009, by Debian. Original by Info-ZIP.

for file in ex*.zip
do
  unzip -j $file '*.csv'
done

답변3

사용하다퓨즈파일 시스템을 기반으로 하는 디렉터리 트리로 zip 파일에 액세스합니다. 각 zip 파일을 마운트하고 cp일반적인 방법(셸 와일드카드, 명령 등)을 사용하여 액세스합니다.

그리고퓨즈 지퍼:

mkdir mnt
for z in *.zip; do
  fuse-zip -- "$z" mnt
  set mnt/*.csv
  if [ $# -gt 1 ]; then
    echo "Skipping $z because it contains multiple .csv files"
  elif ! [ -e "$1" ]; then
    echo "Skipping $z because it does not contain a .csv file"
  else
    cp -- "$1" "${z%.zip}.csv"
  fi
  fusermount -u mnt
done

같은 방법을 사용하시면 됩니다archivemount바꾸다 fuse-zip.

게다가AVFS다르게 작동합니다. 이 보기에서는 전체 파일 시스템에 대한 보기를 생성합니다. ~/.avfs아카이브 파일이 있는 경우 /path/to/foo.zip이름 아래의 디렉터리로 액세스할 수 있습니다 ~/.avfs/path/to/foo.zip#.

mountavfs
cd "$HOME/.avfs$PWD"
for z in *.zip; do
  set -- "$z#/"*.csv
  if [ $# -gt 1 ]; then
    echo "Skipping $z because it contains multiple .csv files"
  elif ! [ -e "$1" ]; then
    echo "Skipping $z because it does not contain a .csv file"
  else
    cp "$1" "${z%.zip}.csv"
  fi
done

배열이 있는 셸을 사용하고 와일드카드가 일치하지 않을 때 빈 목록을 얻는 방법을 사용하면 약간 더 읽기 쉬운 스크립트를 얻을 수 있습니다. 예를 들어 ksh93에서는 fusion-zip을 사용합니다.

#!/bin/ksh
mkdir mnt
for z in *.zip; do
  fuse-zip -- "$z" mnt
  csv=(~(N)"$z/"*.csv)
  if ((${#csv[@]} > 1)); then
    echo "Skipping $z because it contains multiple .csv files"
  elif ((${#csv[@]} == 0)); then
    echo "Skipping $z because it does not contain a .csv file"
  else
    cp -- "$1" "${z%.zip}.csv"
  fi
  fusermount -u mnt
done

zsh에서는 를 사용하고 csv=($z/*.csv(N))bash에서는 csv=($z/*.csv)먼저 실행하십시오 shopt -s nullglob.

답변4

모든 파일이 이 패턴과 일치한다고 가정하면 CW2178470.zip항상 다음에서 추출해야 합니다.CW2178470/CW2178470.csv

이는 비교적 쉽습니다.

for i in ./*.zip
do
   SERIAL=$(echo "$i" | sed -e 's,^.*/,,' -e 's,.zip$,,' )
   unzip "$i" "${SERIAL}/${SERIAL}.csv"
done

이보다 더 똑똑한 논리가 필요하다면 아마도 그것을 살펴보고 추출할 것 perl입니다 Archive::Zip.

관련 정보