How to diff different files in two different directories and store the different files in a new directory

Viewed 114

I have two directories, dir1 and dir2 with m and n files in them, respectively. the condition may be either m>n or m

I want to diff the files in both the directories and want to store the diffed files in a new directory, diffdir.

So the diffdir should have only files that differs in both the dir.

I used

diff -r dir1 dir2 |  grep dir2

It gives me the files that are different in both the directories

diff -r dir1/DISP.case_sc.in.XXX dir2/**DISP.case_sc.in.XXX**

where XXX may varies from 001 to 999 (I have manually added ** here to make the name bold). I need only files (bold one) in diffdir

as number of files in both the directories are not same so in case of m>n it also gives as the output of above command (diff -r dir1 dir2 | grep dir2)

Only in dir2: DISP.case_sc.in.YYY

I also want these DISP.case_sc.in.YYY files in diffdir. Here YYY are the number of files that are equal to the difference m-n. Example if m=020 and n=010 so this YYY will vary from 011 to 020.

In both the dirs (1&2) some files will be exactly same that are not printed with the diff command, I need those files in a another directory name nodiffdir.

Sample input with files named to indicate their relationship to each other:

dir1
    dir1_only
    comm_diff
    comm_same

dir2
    dir2_only
    comm_diff
    comm_same

Expected output (dir1 and dir2 left unchanged):

samedir
    comm_same   # copied as-is from dir1 or dir2

diffdir
    comm_diff   # output of "diff dir1/comm_diff dir2/comm_diff"
    dir1_only   # copied as-is from dir1
    dir2_only   # copied as-is from dir2
2 Answers
$ cat tst.sh
#!/usr/bin/env bash

mkdir -p samedir &&
cp -r dir1 diffdir &&
cp dir2/* diffdir &&
for f1 in dir1/*; do
    fname="${f1##*/}"
    f2="dir2/${fname}"
    if [ -f "$f2" ]; then
        if diff -- "$f1" "$f2" > "diffdir/${fname}"; then
            cp -- "$f1" samedir &&
            rm "diffdir/${fname}"
        fi
    fi
done

.

$ mkdir dir1
$ mkdir dir2
$ echo 'a' > dir1/dir1_only
$ echo 'a' > dir2/dir2_only
$ echo 'b' > dir1/comm_same
$ echo 'b' > dir2/comm_same
$ echo 'c' > dir1/comm_diff
$ echo 'd' > dir2/comm_diff

.

$ ls *
tst.sh

dir1:
comm_diff   comm_same   dir1_only

dir2:
comm_diff   comm_same   dir2_only

.

$ ./tst.sh

.

$ ls *
tst.sh

diffdir:
comm_diff   dir1_only   dir2_only

dir1:
comm_diff   comm_same   dir1_only

dir2:
comm_diff   comm_same   dir2_only

samedir:
comm_same

.

$ awk 'FNR==1{print ORS FILENAME} 1' samedir/* diffdir/*

samedir/comm_same
b

diffdir/comm_diff
1c1
< c
---
> d

diffdir/dir1_only
a

diffdir/dir2_only
a

This might work for you (GNU sed):

mkdir dir3
diff -r dir1 dir2 |
sed '/dir2/!d;s#: #/#;s/.* //;s/.*/cp & &/;s/dir2/dir3/2'

Make a new directory dir3

Diff the two directories dir1 and dir2 and pipe the output to a sed invocation.

Convert each line that contains dir2 into a copy command.

If the output, matches what you expect then copy for real by adding an e command:

mkdir dir3
diff -r dir1 dir2 |
sed '/dir2/!d;s#: #/#;s/.* //;s/.*/cp & &/;s/dir2/dir3/2;e'
Related