3

Background

iPhone has live photo's, i thought i could use VLC on Windows or some iPhone app to take a still of the desired frame. Long story short, you can but the quality of the image as well as the resolution is drastically lowered. So i gave up on this.

Problem

I have actual movie files hidden along side the Live Photo's

My Goal

Using cygwin to run a bash shell script to iterate through 0000 to 9999 and find all JPG and MOV files that have the same name ONLY.

Problem

I am having issues with the regex

I tried ls | grep -E "IMG_0016\.(JPG|MOV)"

I need a bash script that will return true if it finds both a jpg and mov file for the given filename. Is this doable in a one liner? Can anyone give me some ideas on how to make the above bash command more robust?

It finds both but how do i say, okay, good job, you have both, now do the following with those two files.

EDIT

!/bin/bash

for i in $(seq -f "%04g" 0 20)
do
  FILENAME="IMG_$i"
  #echo "$FILENAME"
  var=$(ls -l | grep "$FILENAME" | grep -E "(JPG|MOV)" | wc -l)
  if [ "$var" == 2 ] ; then
    echo we found both for $FILENAME
    echo $var
  fi
done

Output

we found both for IMG_0018
2
we found both for IMG_0019
2

EXPECTED

files in directory are:

  • IMG_0016.JPG
  • IMG_0018.JPG
  • IMG_0018.MOV
  • IMG_0019.JPG
  • IMG_0019.MOV

COMMENT

This is good in the sense that it looks for only 2 files but there has to be a better way to say find ONE JPG and ONE MOV??

EDIT 2

#!/bin/bash

for i in $(seq -f "%04g" 0 20)
do
  FILENAME="IMG_$i"
  #echo "$FILENAME"
  var=$(ls -l | grep "$FILENAME" | grep -E "(JPG|MOV)" | wc -l)
  #echo $var
  if [ "$var" == 2 ] ; then
    #echo we found both for $FILENAME
    var=$(ls -l | grep "$FILENAME" | grep -E JPG | wc -l)
    if [ "$var" == 1 ] ; then
      var=$(ls -l | grep "$FILENAME" | grep -E MOV | wc -l)
      if [ "$var" == 1 ] ; then
        mv "D:\Mike\Pictures\TEST\\$FILENAME.JPG" "D:\Mike\Pictures\TEST\MATCH\\$FILENAME.JPG"
        mv "D:\Mike\Pictures\TEST\\$FILENAME.MOV" "D:\Mike\Pictures\TEST\MATCH\\$FILENAME.MOV"
      fi
    fi
  fi
done
Community
  • 1
  • 1
codeCompiler77
  • 508
  • 7
  • 22
  • `[[ -f IMG_016.JPG && -f IMG_O16.MOV ]]` should return true only if both files exist. Append `; echo File Pair status=$?` to see a visual value. Good luck. – shellter Apr 02 '16 at 22:21
  • @shellter Thanks for the reply! I added my move.sh file. I tried your above code but sorry being new. i wasn't sure how to use it. I tried `ls | grep [[ -f IMG_018.JPG && -f IMG_O18.MOV ]]` which didn't work – codeCompiler77 Apr 02 '16 at 22:27

2 Answers2

2

awk to the rescue!

$ ls -1 | awk -F. '$2~/^(JPG|MOV)$/{a[$1]++} a[$1]>1{print $1}'

will print the file name without suffix for the cases where both extension exist. If you want to print both file names, change the last print block to {print $1".JPG"; print $1".MOV"}

ls -1 creates the file list, one file per line. awk -F. tells awk to use dot as a field delimiter so that second field is the extension. We check whether second field matches either choice. If so, increment the array indexed with the file name. Since file names are unique (up to extension) for any value greater than one should be these two extensions. In the last block we check that condition and print. Assumes the file names don't have dot delimiter other than the one before extension.

You can use the standard tools with the filtered list, for example pipe to

... {print $1}' | xargs -I file mv file.{JPG,MOV} targetdirectory

replace targetdirectory with the real name. Note that {print $1} is a better alternative here.

UPDATE Based on updated requirements, a letter suffix to the file name will be ignored and if there are three instances of the files they need to be filtered as well. This requires a slight change, first to filter letter suffix (one or more) to the file name, and printing the file list at the end only for which the count is 2.

awk -F. '$2~/^(jpg|mov)$/{sub(/[a-z]+$/,"",$1); a[$1]++} 
                      END{for(k in a) if(a[k]==2) print k}'  

and pipe as before to mv

karakfa
  • 66,216
  • 7
  • 41
  • 56
  • That's actually perfect but can you please explain how it works, as much as i appreciate the answer, i want to learn and understand :) I also tried to change it as you suggested to `ls -1 | awk -F. '$2~/^(JPG|MOV)$/{a[$1]++} a[$1]>1{print $1".JPG"; print $1".MOV"}}'` but that doesn't work, newline and asks for `>` additional input. – codeCompiler77 Apr 02 '16 at 23:02
  • you have an extra `}` – karakfa Apr 02 '16 at 23:03
  • Thank you for the explanation! The a[$1] i guess is what iterates the array? That's so much simpler than what i have written above =D One last question if you don't mind, is it possible to add onto that a move command. So move all the files that came back as true to a different folder? – codeCompiler77 Apr 02 '16 at 23:10
  • My massive bash file got reduced to a one liner XD. There is only one issue with the regex above that i just noticed. If there is 3 files `IMG_0018.JPG`, `IMG_0018a.JPG` and `IMG_0018.MOV`, i don't want it to move anything. `IMG_0018.` is the exact thing i am looking for and only that. – codeCompiler77 Apr 02 '16 at 23:53
1
for movfile in IMG_[0-9][0-9][0-9][0-9].MOV ; do
    base=${movfile%.MOV}
    jpgfile=$base.JPG

    if [[ -e $jpgfile ]] ; then
        echo "we found both for $base"
    fi
done
pjh
  • 6,388
  • 2
  • 16
  • 17