파일을 재귀적으로 추출하지만 자체 폴더에 보관하는 방법은 무엇입니까?

파일을 재귀적으로 추출하지만 자체 폴더에 보관하는 방법은 무엇입니까?

다음은 폴더의 모든 파일을 재귀적으로 추출하는 방법입니다.

find -iname \*.epub -exec unzip -o {} \;

그러나 추출된 파일은 모두 상위 폴더에 저장됩니다.

Parent (Extracted Epub files)
  Child (Epub files)
  Child (Epub files)

명령을 자체 폴더로 추출하도록 명령을 어떻게 변경할 수 있습니까?

Parent
  Child (Epub files and extracted Epub files)
  Child (Epub files and extracted Epub Files)

답변1

GNU를 사용하는 경우 find해당 작업을 사용하십시오 -execdir.

find -iname \*.epub -execdir unzip -o {} \;

이는 파일이 발견된 모든 디렉토리에서 실행되어 unzip파일이 적절한 하위 디렉토리에 추출되도록 합니다.

시작 디렉터리(특히 OpenBSD):

find /path/to/start -iname \*.epub -execdir unzip -o -- {} \;

답변2

Stephen Kitt의 -execdir답변은 훌륭합니다.하지만여러 파일이 .epub동일한 디렉터리에 있을 수 있는 경우( -execdir도움이 되지 않음) 다음을 수행해야 합니다.

find ./ -iname '*.epub' -exec sh -c '
  for f; do
    rp="$(realpath -e "$f")"
    bn="$(basename "$f" .epub)"
    dn="$(dirname "$rp")/$bn"

    [ -e "$dn" ] && continue
    echo mkdir -p "$dn"
    echo unzip -d "$dn" -o "$rp"
  done' find-sh {} +

"$f"sh 스크립트에 전달된 각 매개변수( )에 대해 realpath전체 절대 경로 이름을 변수로 가져오는 데 사용된 rp다음 basename.epub 확장자가 없는 기본 파일 이름을 변수로 가져오는 데 사용됩니다 bn. dirname절대 디렉토리 이름을 가져와 "/$bn"변수에 추가하는 데 사용됩니다 dn. 그건 그렇고, 세 가지 프로그램 모두 GNU에 있습니다핵심 도구.

이미 존재하는 경우 "$dn"명령문에서 이를 건너뜁니다. continue필요한 경우 더 많은 오류 검사 및 오류 처리 코드를 추가하는 것이 좋습니다. 그렇지 않으면 mkdir -punzip 옵션으로 생성되어 매개변수로 사용된다 -d. "$rp"사용할 파일 이름 인수입니다 unzip.

참고: 이것은 시험 실행으로 작성되었으므로 요청한 내용만 인쇄합니다.회의하고 있지만 실제로는 하지 않습니다. echo실제로 디렉토리를 생성하고 디렉토리에 .epub 파일을 추출하도록 명령에서 명령문을 제거하십시오 .

echo "$rp"또는 문을 추가 echo "$f"하고 unzip's -q옵션을 사용하여 파일 이름을 반복하는 동안 진행 상황을 계속 표시하면서 출력의 노이즈 양을 줄일 수 있습니다.

답변3

GNU를 사용 sed하고 find현재 일반적인(표준은 아니지만) -iname/ -print0조건자 구현을 지원하면 다음을 수행할 수 있습니다.

LC_ALL=C find . -iname '?*.epub' \
              ! -name '*[[*?]*' \
              ! -iname ..epub \
              ! -iname ...epub \
                -type f -print0 |
  LC_ALL=C sed -z 'h;s/\.epub$//;p;g' |
  xargs -r0n2 unzip -d

( 일치하는 파일을 찾기 위해 와일드카드로 처리하는 버그를 해결하려면 또는 [문자 가 포함된 파일 이름을 건너뛰십시오 .)*?unzip

어느 것이 실행될 것인가

unzip -d ./path/to/file ./path/to/file.epub

epub확장자 없이 파일 이름을 딴 디렉터리에 파일 내용을 추출합니다 .

또한 해당 디렉터리가 문제 가 될 수 있으므로 건너뛰고 .epub( ?*앞에 최소 1바이트 필요 .) ..epub파일 을 건너뜁니다....epub""...

또는 zsh를 사용하십시오.

set -o extendedglob
for f (./**/(^*[[*?]*).(#i)epub(N.)) unzip -d $f:r $f

./**/(^(|.|..|*[[?*]*)).(#i)epub(ND.)여기서는 숨겨진 항목을 생략하고, 필요한 경우 glob을 로 변경합니다(다시 .epub제외 ..epub) ...epub.

zsh를 사용하면 문자를 다음으로 대체하여 문제를 더 잘 해결할 수 있습니다.[?**[*]?[?]

set -o extendedglob
for f (./**/*.(#i)epub(N.)) unzip -d $f:r $f:h/${${f:t}//(#m)[[?*]/[$MATCH]}

또는 libarchive와 같은 Unixy 명령을 사용하여 zip 아카이브를 추출할 수 있습니다 bsdtar.

set -o extendedglob
for f (**/*.(#i)epub(N.)) {
  mkdir -p -- $f:r && bsdtar -C $f:r -xf $f
}

또는 find숨겨진 항목을 사용하고 포함합니다.

LC_ALL=C find . -iname '?*.epub' ! -iname ..epub ! -iname ...epub -exec sh -c '
  for file do
    dir=${file%.*}
    mkdir -p "$dir" &&
      bsdtar -C "$dir" -xf "$file"
  done' sh {} +

관련 정보