Running diff and stopping the difference

I have a script project that checks directories with multiple values ​​and compares them with extended archive files of the same directories elsewhere.

I use it diff -r -q, and I would like for it to diffdetect any difference in the recursive run, it will stop working, and will not go through other directories in the same run.

All help appreciated!

thank

@bazzargh I tried this as you suggested or like this.

for file in $(find $dir1 -type f); 
do if [[ $(diff -q $file ${file/#$dir1/$dir2}) ]]; 
then echo differs: $file > /tmp/$runid.tmp 2>&1; break; 
else echo same: $file > /dev/null; fi; done 

But this only works with files that exist in both directories. If one file is missing, I will not receive information about it. In addition, in the directories I work with, there are more than 300,000 files, so for each file there is a bit of overhead to do findfor each file, and then diff.

I would like something like this to work, with an instruction elifthat checks to see if $runid.tmpdata contains gaps if that happens. I added 2>after the first statement if, so it is stderrsent to a file $runid.tmp.

for file in $(find $dir1 -type f); 

do if [[ $(diff -q $file ${file/#$dir1/$dir2}) ]] 2> /tmp/$runid.tmp; 

then echo differs: $file > /tmp/$runid.tmp 2>&1; break; 

elif [[ -s /tmp/$runid.tmp ]]; 

then echo differs: $file >> /tmp/$runid.tmp 2>&1; break;

else echo same: $file > /dev/null; fi; done

Will this work?

+3
source share
4 answers

"find" , . , dirs foo, bar:

for file in $(find foo -type f); do if [[ $(diff -q $file ${file/#foo/bar}) ]]; then   echo differs: $file; break; else echo same: $file; fi; done

NB , "" , "foo".

: , :

diff -rq foo bar | head -n1
+5

'diff', 'awk' ( ), , .

- (, )

awk '{ h[$0] = ! h[$0] } END { for (k in h) if (h[k]) exit }' file1 file2

.

. , , awk. . .

+1

:

#!/usr/bin/env bash

# Determine directories to compare
d1='./someDir1'
d2='./someDir2'

# Loop over the file lists and diff corresponding files
while IFS= read -r line; do

  # Split the 3-column `comm` output into indiv. variables.
  lineNoTabs=${line//$'\t'}
  numTabs=$(( ${#line} - ${#lineNoTabs} ))

  d1Only='' d2Only='' common=''
  case $numTabs in
    0)
      d1Only=$lineNoTabs
      ;;
    1)
      d2Only=$lineNoTabs
      ;;
    *)
      common=$lineNoTabs
      ;;
  esac

  # If a file exists in both directories, compare them,
  # and exit if they differ, continue otherwise
  if [[ -n $common ]]; then
    diff -q "$d1/$common" "$d2/$common" || {
       echo "EXITING: Diff found: '$common'" 1>&2;
       exit 1; }
  # Deal with files unique to either directory.
  elif [[ -n $d1Only ]]; then # fie
    echo "File '$d1Only' only in '$d1'."
  else # implies: if [[ -n $d2Only ]]; then
    echo "File '$d2Only' only in '$d2."    
  fi

  # Note: The `comm` command below is CASE-SENSITIVE, which means:
  #   - The input directories must be specified case-exact.
  #     To change that, add `I` after the last `|` in _both_ `sed commands`.
  #   - The paths and names of the files diffed must match in case too.
  #     To change that, insert `| tr '[:upper:]' '[:lower:]' before _both_
  #     `sort commands.

done < <(comm \
  <(find "$d1" -type f | sed 's|'"$d1/"'||' | sort) \
  <(find "$d2" -type f | sed 's|'"$d2/"'||' | sort))

( find), ( sed ) , comm, , , (, , ), , , .

, diff ed , . , 1- 2- .

, comm , :

  • read will handle multiple tabs in a sequence as one separator
  • commdisplays a variable number of tabs; for example, if there is only the value of the 1st column, no tab is displayed at all.
+1
source

I got a solution to this thanks to @bazzargh.

I use this code in my script and now it works fine.

for file in $(find ${intfolder} -type f);
do if [[ $(diff -q $file ${file/#${intfolder}/${EXPANDEDROOT}/${runid}/$(basename ${intfolder})}) ]] 2> ${resultfile}.tmp;
then echo differs: $file > ${resultfile}.tmp 2>&1; break;
elif [[ -s ${resultfile}.tmp ]];
then echo differs: $file >> ${resultfile}.tmp 2>&1; break;
else echo same: $file > /dev/null;
fi; done

thank!

0
source