파일 이름을 기준으로 이미지를 필터링하는 이유는 무엇입니까?

파일 이름을 기준으로 이미지를 필터링하는 이유는 무엇입니까?

아래 코드를 사용하여 이미지를 필터링할 때 파일도 필터링해야 합니다.

예를 들어,IMG_0079.JPG.JPG, 아래 코드를 실행하면 .JPG첨부된 파일을 필터링할 수 있습니다. 이유를 알 수 없는 것 같습니다.

  • 입력이 올바른지 확인하세요.

    if [ $# != 2 ]; then
       echo "Usage: phar image_path archive_path" && exit;
    fi
    
  • 대상 디렉터리가 존재하지 않으면 디렉터리가 생성됩니다.

    mkdir -p $2
    
  • 파일에 필요한 접미사를 찾아 복사하고 추가하는 명령문

    find $1 -iname IMG_[0-9][0-9][0-9][0-9].JPG -exec cp -b --suffix=.JPG 
    {} $2 \; 
    echo complete!
    
  • 중복된 문을 확인하고 제거하세요. 각 파일의 md5를 비교합니다.

        shopt -s nullglob              
        for file in "$2"/* 
        do
          md5sum=$(md5sum < "$file")        
          echo "-- Found: $file ($md5sum)"
          for duplicate in "$2"/*     #loop to find/remove duplicates
          do
            [ "$file" = "$duplicate" ] && continue      
            #comparison of 2 files
            [ "$md5sum" = "$(md5sum < "$duplicate")" ] && rm -v             
            "$duplicate"     
            #removal of duplicates
          done
        done
    

답변1

내가 올바르게 이해했다면 문제는 다음과 같습니다.

find $1 -iname IMG_[0-9][0-9][0-9][0-9].JPG

.JPG.JPG처음에는 파일을 찾지 못했습니다 . 바라보다:

mkdir JPG
for n in 9 8 7 6 5 4 3 2 1
    do touch ./JPG/IMG_000${n}.JPG
done
find ./JPG -iname IMG_[0-9][0-9][0-9][0-9].JPG

###OUTPUT###

./JPG/IMG_0001.JPG
./JPG/IMG_0002.JPG
./JPG/IMG_0003.JPG
./JPG/IMG_0004.JPG
./JPG/IMG_0005.JPG
./JPG/IMG_0006.JPG
./JPG/IMG_0007.JPG
./JPG/IMG_0008.JPG
./JPG/IMG_0009.JPG

이제 나는...

for f in ./JPG/* ; do touch ${f}.JPG ; done && ls ./JPG

IMG_0001.JPG      IMG_0003.JPG.JPG  IMG_0006.JPG      IMG_0008.JPG.JPG
IMG_0001.JPG.JPG  IMG_0004.JPG      IMG_0006.JPG.JPG  IMG_0009.JPG
IMG_0002.JPG      IMG_0004.JPG.JPG  IMG_0007.JPG      IMG_0009.JPG.JPG
IMG_0002.JPG.JPG  IMG_0005.JPG      IMG_0007.JPG.JPG
IMG_0003.JPG      IMG_0005.JPG.JPG  IMG_0008.JPG

find지금 우리에게 무엇이 표시되는지 살펴보겠습니다 .

find ./JPG -iname IMG_[0-9][0-9][0-9][0-9].JPG

###OUTPUT###

./JPG/IMG_0001.JPG
./JPG/IMG_0002.JPG
./JPG/IMG_0003.JPG
./JPG/IMG_0004.JPG
./JPG/IMG_0005.JPG
./JPG/IMG_0006.JPG
./JPG/IMG_0007.JPG
./JPG/IMG_0008.JPG
./JPG/IMG_0009.JPG

알다시피, 내 .JPG.JPG파일 이름은 문자열로 끝나지 않기 때문에 [0-9]{4}.JPG find처음에는 표시되지 않습니다. \*해당 검색 문자열 끝에 를 추가하면 -iname더 잘 작동할 수 있습니다.

그러나 또 다른 답변에서 언급했듯이 또 다른 문제는 쉘 볼입니다. 예를 들어:

sh -cx 'cd ./JPG ; find . -iname IMG_[0-9][0-9][0-9][0-9].JPG'                                                                      
+ cd ./JPG
+ find . -iname IMG_0001.JPG IMG_0002.JPG IMG_0003.JPG IMG_0004.JPG IMG_0005.JPG IMG_0006.JPG IMG_0007.JPG IMG_0008.JPG IMG_0009.JPG
find: paths must precede expression: IMG_0002.JPG
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]

바라보다? 쉘이 가능하다면 [glob]명령 string 을 전달하기 전에 얻은 인용되지 않은 대괄호 안에 있을 것입니다 find. 아마도 다음과 같이 보일 것입니다.

find "$1" -iname 'IMG_[0-9][0-9][0-9][0-9].JPG*'

마지막 점에 관해서는 아마도 그렇게 많은 재귀 루프가 필요하지 않을 것입니다. 제 생각에는 오래된 백업만 제거하려는 경우 cp --suffix=.JPG -b모든 것을 대체할 수 있는 실행 가능한 방법이 될 수 있습니다 shopt....

(   dir=$2
    set -- "${dir}"/*[0-9].???
    while [ -e "$1" ]
    do  cmp "$1" "${1}.JPG" &&
        rm -v "${1}.JPG" 2>&1
    shift ; done
) 2>/dev/null

그러나 이것이 방법을 통해 상당 부분 최적화될 수 있다는 것은 부인할 수 없습니다.약간다음과 같은 재귀 루프:

(   dir=$2
    set -- "${dir}"/*[0-9].???
    while [ -e "$1" ]
    do  until [ -e "${1}.JPG" ] 
        do shift || break; done
        cmp "$1" "${1}.JPG" &&
        rm -v "${1}.JPG" 2>&1
    ${1+shift} ; done
) 2>/dev/null 

나는 말했다약간whileuntil루프는 모두 동일한 매개변수 세트에서 실행되고 동일한 파일을 두 번 테스트하지 않기 때문에 정확히 동일하지 않습니다.재귀중첩되어 있더라도 마찬가지입니다. 어쨌든 최적화는 exec추가 절차를 요구하지 않고 until가능할 때마다 쉘 내장에만 의존하는 것으로 구성됩니다.

답변2

for당신이 언급한 루프에서 나에게 오류가 발생했습니다. 하지만 대괄호에 이스케이프 문자를 사용하면 제대로 작동합니다. 따라서 내 for 루프는 다음과 같습니다.

find $1 -iname IMG_\\[0-9\\]\\[0-9\\]\\[0-9\\]\\[0-9\\].JPG -exec cp -b --suffix=.JPG  {} $2 \;

관련 정보