조건부로 중복 파일 제거

조건부로 중복 파일 제거

파일이 동일한 이름을 공유하는 경우에만 중복 항목을 제거하고 싶습니다.
예: rdfind -deleteduplicates true ~/folder내 목표는 달성되지 않을 것입니다.

한 가지 아이디어는 rdfind 시험 실행의 출력(results.txt)을 얻는 것입니다.

rdfind -n true "$PWD"

다음으로 시작하여 식별되는 각 그룹의 첫 번째 파일과 동일한 이름을 가진 파일을 확인합니다.DUPTYPE_FIRST_OCCURRENCE XXXX

DUPTYPE_FIRST_OCCURRENCE 5148 2 37934240 2054 16916792 1 /home/fig3.tif
DUPTYPE_WITHIN_SAME_TREE -5148 3 37934240 2054 17044654 1 /home/other/fig3.tif
DUPTYPE_WITHIN_SAME_TREE -5148 3 35435435 2054 16546546 1 /home/other2/fig3.tif

DUPTYPE_FIRST_OCCURRENCE 5160 2 116397930 2054 16916804 1 /home/file.psd
DUPTYPE_WITHIN_SAME_TREE -5160 2 116397930 2054 16916870 1 /home/folder/file.psd
DUPTYPE_WITHIN_SAME_TREE -5160 2 116397930 2054 17654654 1 /home/folder/file2.psd

위의 예에서 첫 번째 그룹의 경우 중복 항목 2개를 제거해야 하고, 두 번째 그룹에서는 첫 번째 항목과 이름이 동일한 중복 항목 하나만 제거해야 합니다(file.psd).

편집 : rmlint의 답변이 바람직합니다. "원시" 파일은 일반적으로 다음을 사용하여 생성할 수 있습니다.린트

답변1

results.txtrdfind이 스크립트는 질문에 표시된 대로 생성된 파일을 사후 처리합니다 .

#!/bin/bash
#
while read -r type x x x x x x path
do
    case "$type" in

        DUPTYPE_FIRST_OCCURRENCE)
            name="${path##*/}"
            echo "New path for $name" >&2
            ;;

        DUPTYPE_WITHIN_SAME_TREE|DUPTYPE_OUTSIDE_TREE)
            if [[ -n "$name" ]] && [[ ${path##*/} == $name ]]
            then
                echo "Remove duplicate $path" >&2
                # rm -f "$path"
            else
                echo "Skipping differently named $path" >&2
            fi
            ;;
    esac
done

rm작업을 수행할 준비가 되면 주석 처리를 해제하세요. echo명령문을 주석 처리 하거나 리디렉션합니다.표준 에러) 장황한 내용을 원하지 않는 경우.

read -r type x x x x x x path루프 상단의 명령문은 공백으로 구분된 8개의 필드를 읽습니다. 가운데 6개는 관련이 없으므로 가비지 변수로 읽어들여 합계만 사용 $type합니다 $path.

생산하다results.txt

rdfind -dryrun true -makeresultsfile true {directory...}

생성된 파일의 후처리( rddedup위에 표시된 내 스크립트입니다)

rddedup < results.txt

답변2

이 고양이의 가죽을 다른 방법으로 벗기는 방법은 무엇입니까? ( rmlint이 글을 게시하려고 할 때 OP 편집 요청이 이루어졌지만 신경 쓰지 마세요. 이것도 게시될 수 있습니다...하단의 편집을 참조하세요 rmlint)

구조가 알려져 있으므로 파일 이름의 첫 번째 발생이 대상이고 빈 줄이 제거되기 전의 후속 중복이므로 awk@roaima보다 약간 느리기는 하지만 재미있을 수도 있습니다.

awk 'NF==0{getline; target=""}
     target==""{l=split($8,t,"/"); target=t[l];getline}
     {l=split($8,q,"/");if (q[l]==target)print $8}' file1 | while read f; do echo rm $f ; done

송곳

빈 줄이 있으면 건너뛰고 대상 파일 이름을 다음으로 재설정하세요.""

awk 'NF==0{getline; target=""}

대상이 설정되지 않은 경우(즉, 각 빈 줄 뒤와 시작 부분) 이 줄에서 대상 파일 이름을 가져와 다음 줄로 이동합니다.

     target==""{l=split($8,t,"/"); target=t[l];getline}

이제 현재 줄의 파일 이름을 대상과 비교하여 일치하는 경우 전체 경로를 출력합니다.

     {l=split($8,q,"/");if (q[l]==target)print $8}' file1

그런 다음 루프를 통해 awk실제 삭제(삭제만)를 수행합니다 .echo

    | while read f; do echo rm $f ; done

이 작업을 수행할 수도 있지만 (다시 삭제하면 됩니다 echo)

     {l=split($8,q,"/");if (q[l]==target)print $8}' file1 | xargs echo rm

편집하다우수한rmlint앞은 당신이 쉽게 통제할 수 없는 우선순위인 것 같아요독창성

기본적으로 rmlint 명령에 여러 경로를 지정하면 첫 번째 명명된 경로의 파일이 나중에 명명된 경로보다 더 "원본"인 것으로 간주됩니다. 동일한 경로에 두 개의 파일이 있는 경우 이전 파일이 원본 파일로 간주됩니다. 수정 시간이 동일한 경우 어느 것이 원본으로 선택되는지는 단지 우연의 문제입니다.

그러나 명시적인 예의 경우 이 옵션(원래 파일 계층 구조에서 가장 낮은 수준)은 콘텐츠가 아닌 파일 이름을 기준으로 한 일치 -d와 함께 사용됩니다 .-b

rmlint -d -b /home/

틀림없이 이것은많은내 스크립트보다 짧지만 rmlint스크립트를 작성하는 것보다 페이지를 읽는 데 시간이 더 걸립니다. 골라보세요.

테스트되지 않은, btw ...

답변3

다음은 중복 항목이 서로 일치하지만 주어진 파일 목록의 첫 번째 항목이 아닌 상황에 대해 수정된 roaima의 스크립트입니다. 예를 들어. 동일한 파일에는 a/x, , b/y의 세 가지 이름이 있습니다 c/y. 그런 다음 a/x기본 파일( DUPTYPE_FIRST_OCCURRENCE)이 제거되면 다른 파일 중 하나가 삭제됩니다.

#!/bin/bash

while read -r type x x x x x x path
do
    name="${path##*/}"
    [[ "$type" == '#' ]] || [[ -z "$name" ]] && 
        printf "%s\n" "skipping a non-entry looking line">&2
    case "$type" in
        DUPTYPE_FIRST_OCCURRENCE)
            printf "New path for %s: %s\n" "$name" "$path">&2
            unset ass
            declare -A ass
            ass["$name"]=1
            ;;

        DUPTYPE_WITHIN_SAME_TREE|DUPTYPE_OUTSIDE_TREE)
            if [ "${ass["$name"]}"x != "x" ]
            then
                printf "Remove duplicate: %s\n" "$path" >&2
                # rm -f "$path"
            else
                ass["$name"]=1
                printf "Skipping differently named file: %s\n" "$path" >&2
            fi
            ;;
    esac 
done < results.txt

일부 다른 변경 사항이 포함되어 있으며 주석 없이 읽을 수 있습니다. ass연관 배열입니다.

이 스크립트는 완전히 테스트되지 않았으므로 아직 해결되지 않은 특수 사례가 있을 수 있다는 점을 인정해야 합니다.

사용 예. rdfind -n true .그러면 우리는 이것을 얻습니다:

$ ls *
results.txt  script.bash

a:
filea0  filea1  fileb0

b:
filea1  fileb0

c:
fileb0

결과.txt:

$ cat results.txt 
# Automatically generated
# duptype id depth size device inode priority name
DUPTYPE_FIRST_OCCURRENCE 4 1 6 64773 4849814 3 ./a/filea0
DUPTYPE_WITHIN_SAME_TREE -4 1 6 64773 4849816 3 ./b/filea1
DUPTYPE_WITHIN_SAME_TREE -4 1 6 64773 4849817 3 ./a/filea1
DUPTYPE_FIRST_OCCURRENCE 6 1 6 64773 4849677 3 ./a/fileb0
DUPTYPE_WITHIN_SAME_TREE -6 1 6 64773 4849819 3 ./b/fileb0
DUPTYPE_WITHIN_SAME_TREE -6 1 6 64773 4986586 3 ./c/fileb0
# end of file

실행 중인 스크립트:

./script.bash
skipping a non-entry looking line
skipping a non-entry looking line
New path for filea0: ./a/filea0
Skipping differently named file: %s\n ./b/filea1
Remove duplicate: ./a/filea1
New path for fileb0: ./a/fileb0
Remove duplicate: ./b/fileb0
Remove duplicate: ./c/fileb0
skipping a non-entry looking line

관련 정보