여러 zip 파일 중 디렉터리 구조에 원본 파일이 포함되어 있는지 확인하세요.

여러 zip 파일 중 디렉터리 구조에 원본 파일이 포함되어 있는지 확인하세요.

여기에 매우 어려운 문제가 있습니다.

다양한 폴더에 많은 사진이 들어 있는 사진 라이브러리가 있습니다.

그러다가 구글 포토를 이용해 사진을 찍기 시작했고, 그 원본을 구글 포토에 넣고 5년 넘게 사용했어요.

이제 Google 포토를 포기하고 싶습니다. 모든 사진을 Google로 내보내고 약 1.5TB(150 x ~10GB 파일) 상당의 모든 Zip 파일을 다운로드했습니다.

이제 원래 디렉토리 구조를 유지하고 Google 포토에서 모든 중복 파일을 제거하고 싶습니다. 이 작업 후에는 기본적으로 각각 고유한 파일이 포함된 두 개의 디렉터리가 남길 원합니다. 그런 다음 나중에 수동으로 병합할 수 있습니다.

rmlint중복 항목을 감지하고 Google 드라이브에서 삭제하기 위해 실행할 모든 파일의 추출을 시작했습니다 . 문제는 그걸 다 운영하기에는 공간이 부족해서 30개의 아카이브를 추출한 후 실행하고 rmlint, 지우고, 또 30개 추출하고, rmlint다시 실행하고, 지우는 등의 과정을 거쳐야 한다는 점입니다. 이렇게 하면 원본 파일을 계속해서 다시 스캔하므로 완료하는 데 오랜 시간이 걸립니다. 나는 --xattr후속 실행 속도를 높이기 위해 rmlint 플래그를 사용했습니다. 전체 명령 rmlint은 부록을 참조하세요 .

먼저 모든 아카이브를 추출하지 않고도 이 작업을 수행할 수 있습니까? zip 파일의 파일 체크섬을 사용하고 해당 파일과 비교할 수 있는 방법이 있습니까?

감사해요!

부록

rmlint \
        --xattr \
        -o sh:rmlint-photos.sh \
        -o json:rmlint-photos.json \
        --progress \
        --match-basename \
        --keep-all-tagged \
        --must-match-tagged \
        "/mnt/f/GoogleTakeout/" \
        // \
        "/mnt/e/My Documents/Pictures/" \

답변1

zsh 또는 bash는 물론 libarchive bsdtar및 GNU 에서도 tar다음을 수행할 수 있습니다.

LC_ALL=C find . -name '*.zip' -type f -print0 |
  while IFS= read -rd '' archive; do
    bsdtar -cf - "@$archive" |
      ARCHIVE=$archive tar -xf - --to-command='
        case $TAR_FILETYPE$TAR_FILENAME in
          (f*.jpg | f*.JPG)
            sha1sum | {
              IFS= read -r sum rest &&
                printf "%s\n" "$sum:$ARCHIVE:$TAR_FILENAME"
            }
        esac' > sums.txt

(아카이브 경로나 멤버에 줄바꿈이나 :문자가 포함되어 있지 않다고 가정) 각 아카이브의 목록을 가져옵니다 ( 이미지당 하나가 실행되므로 <checksum>:<archive>:<file-in-archive>시간이 걸립니다 ).sha1sum

그런 다음 다음과 같이 각 고유 체크섬에 대해 하나의 파일만 추출할 수 있습니다.

perl -F: -slane '
  ($sum, $archive, $file) = @F;
  if (!$seen{$sum}++) {
    push @{$files{$archive}}, $file;
  }
  END {
    for $archive (keys %files) {
      open EXTRACT, "|-", "bsdtar", "-C", $dest, "-T", "/dev/stdin", "-xvnf", $archive;
      for (@{$files{$archive}}) {
        s/[][?*\\]/\\$&/g; # escape wildcards
        print EXTRACT;
      }
    }
  }' -- -dest='/mnt/e/My Documents/Pictures/' sums.txt

(더 많은 오류 처리를 추가해야 할 수도 있습니다).

perl그러나 동시에 체크섬 추출을 수행하는 것이 더 효율적일 수 있습니다.

(LC_ALL=C find "$PWD" -name '*.zip' -type f -print0 | {
  cd '/mnt/e/My Documents/Pictures' &&
    perl -MArchive::Zip -MDigest::SHA=sha1 -0lne '
      my $zip = Archive::Zip->new();
      if ($zip->read($_) == AZ_OK) {
        for $member ($zip->membersMatching(".*\.jpe?g")) {
          $zip->extractMember($member)
            unless (!$seen{sha1(zip->contents($member))}++);
        }
      }'
)

(경고: 이것은 모두 테스트되지 않았습니다).

관련 정보