여기에 매우 어려운 문제가 있습니다.
다양한 폴더에 많은 사진이 들어 있는 사진 라이브러리가 있습니다.
그러다가 구글 포토를 이용해 사진을 찍기 시작했고, 그 원본을 구글 포토에 넣고 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))}++);
}
}'
)
(경고: 이것은 모두 테스트되지 않았습니다).