3

When filtering the images using the below code, I also need to filter files.

For example,IMG_0079.JPG.JPG, when running the code below it's allowing files with additional .JPG to get filtered out, and I can't seem to discover why?

  • Checking if the input is correct

    if [ $# != 2 ]; then
       echo "Usage: phar image_path archive_path" && exit;
    fi
    
  • This will create a destination dir if it doesn't exist

    mkdir -p $2
    
  • Statement which finds and copies and adds necessary suffixes to files

    find $1 -iname IMG_[0-9][0-9][0-9][0-9].JPG -exec cp -b --suffix=.JPG 
    {} $2 \; 
    echo complete!
    
  • Check and remove duplicate statement. It will compare the md5 of each file.

        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
    
  • Filter how? What files are you trying to identify and what do you want to do with them? It's not enough to post your script: you also need to tell us what about it you're unhappy with. – Gilles Jul 12 '14 at 19:22
2

If I'm reading this correctly, your problem lies here:

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

This never finds the .JPG.JPG files in the first place. Look:

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

So now I'll...

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

Let's see what find shows us now:

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

So you see, because my .JPG.JPG filenames do not end with the string [0-9]{4}.JPG find never shows them up in the first place. Adding a \* to the end of that -iname search string might work better for you.

Still, as the other answer mentions, another problem is your shell globs. For instance:

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]

You see? If the shell can it will [glob] on those unquoted square brackets you've got before ever even handing the command string to find. It should probably look more like this:

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

And regarding the last bit, you might not need to recursively loop so much. I think - so long as you're only looking to remove old cp --suffix=.JPG -backups - this might do as a workable replacement for everything from shopt... on:

(   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

Though, admittedly, that could be optimized a great deal with one sort of recursive loop like:

(   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 

I say sort of because both while and until loops operate on the same parameter set and never even test the same file twice so they don't exactly recurse even if they are nested. Anyway, the optimization lies in not execing any other process until necessary and relying only on shell builtins as much as possible.

  • @Joseph - please confirm or deny that this addresses your problem. – mikeserv Jul 13 '14 at 2:22
2

The for loop you have mentioned is throwing an error for me. But it works fine when I use escape character for square brackets. So my for loop would be like this:

find $1 -iname IMG_\\[0-9\\]\\[0-9\\]\\[0-9\\]\\[0-9\\].JPG -exec cp -b --suffix=.JPG  {} $2 \;
  • It's working fine both ways for me, however still filtering through duplicates. IMG_0073.JPG & IMG_0073.JPG.JPG. Thats the issue i've came across and cant seem to fix it! – Joseph Jul 11 '14 at 23:12
  • Have no idea, anyway just give it a try. Give $ at the end of JPG in the find command. – beginer Jul 11 '14 at 23:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.