1

I have a series of a few thousand files, all with filenames in order, so let's say file1.x, file2.x, file3.x, etc. All these files are in the same directory.

I know how to generate a diff from file1.x to file2.x, but is there a way I could write a bash script to generate diffs from one file to the next? Basically it would first make the diff from 1 to 2, then 2 to 3, then 3 to 4, etc., until it was completed.

  • It's not clear if you want to diff all the possible combinations, or just each file with the next in line... could you please elaborate on that? – jimm-cl Jul 2 '15 at 3:38
  • each file with the next – diff darrell Jul 2 '15 at 4:05
2

The following script takes an argument like "file*.x" and applies it to find | sort to get a list of files to process. With thousands of files, you may get "too many arguments" by echo file*.x.

#!/bin/bash

prev=
find . -maxdepth 1 -type f -name "$1" | sort -V |
while read -r file; do
        file=${file#*/} # Remove leading ./
        if test -n "$prev"; then
                diff -u "$prev" "$file" > "${prev%.*}-${file%.*}.diff"
        fi
        prev="$file"
done

Sample session:

$ echo a > file1.x
$ echo b > file2.x
$ echo c > file3.x
$ echo d > file5.x
$ echo e > file10.x
$ ./script.sh "file*.x"
$ ls *.diff
file1-file2.diff  file2-file3.diff  file3-file5.diff  file5-file10.diff
1

The following shell script, when given an argument of the form file1.x, generates a series of diffs. It increments the last series of digits in the file name (so you can start at file0.x or file42.x) and goes on until it finds a missing number.

#!/bin/sh
current=$1
suffix=${1##*[0-9]}; digits=${1%"$suffix"}
digits=${digits##*[!0-9]}; prefix=${1%"$digits$suffix"}
while
  leading_zeros=${digits%%[1-9]*}; digits=${digits#$leading_zeros}
  case $digits in
    *[!9]*) digits=$leading_zeros$((digits+1));;
    *) digits=${leading_zeros%0}$((digits+1));;
  esac
  next=$prefix$digits$suffix
  [ -e "$next" ]
do
  diff -u -- "$current" "$next" >"$next.diff"
  current=$next
done

Rather than generate a bunch of diffs, it may be more convenient to enter the versions into version control, and use nice VC tools to explore the successive revisions. To do that, initialize version control (e.g. git init), add the initial file (e.g. cp file1.x file.x && git add file.x && git commit -m "version 1"), and instead of generating diffs (the diff line in the script above) commit the successive versions (e.g. cp -- "$next" "$prefix$suffix" && git commit -m "Version $digits" -- "$prefix$suffix").

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.