bashshellif-statementcpcmp

Using the output of if statement (cmp) in a cp command


I am trying to use the output of an if statement as input for a cp command, but it does not seem to work. My code is:

for fname in $(find $1 -name "IMG_[0-9][0-9][0-9][0-9].JPG")
do
  filename=$(basename $fname)
  if cmp $2/$filename $fname; then 
    cp $fname $2/$filename.JPG
  fi

the output I am getting is

lel//IMG_0039.JPG dir/dir2/IMG_0039.JPG differ: byte 212, line 1 
lel//IMG_2317.JPG dir/dir/IMG_2317.JPG differ: byte 212, line 1

and I want to copy only those two files while giving them .JPG suffix, so they don't overwrite the existing ones in $2, however it copies all the files in folder $1 to folder $2, while giving them the .JPG suffix, so now instead of having copy of the different one I have copies of the same files only that they have suffix .JPG

I think the cp statement is incorrect, as the cmp only gives the difference between the files and then executes the cp if there is a difference. I already copied the files with a for loop, now I am trying to rename and copy the different ones that have same names with the same for but with if statement.


Solution

  • You don't actually care about the output of cmp, only its exit status. If the exit status is non-zero, then the files differ and you presumably want to do the copy. Also, don't bother with find here.

    shopt -s globstar
    for source in "$1"/**/IMG_[0-9][0-9][0-9][0-9].JPG; do
       filename=$(basename "$source")
       target="$2/$filename"
       if ! cmp -s "$source" "$target"; then
           cp "$source" "$target"
       fi
       # cmp -s "$source" "$target" || cp "$source" "$target"
    done
    

    The ! negates the exit status, as if executes the body if the condition has a zero exit status. Since you want to execute when cmp has a nonzero exit status, we negate it first.

    Be sure to quote all your parameter expansions. Leaving them unquoted will break your code if you happen to have a file name like $1/more files/IMG_9342.JPG.