rut2
rut2

Reputation: 706

How to extract only file name return from diff command?

I am trying to prepare a bash script for sync 2 directories. But I am not able to file name return from diff. everytime it converts to array.

Here is my code :

 #!/bin/bash
 DIRS1=`diff -r /opt/lampp/htdocs/scripts/dev/ /opt/lampp/htdocs/scripts/www/ `
 for DIR in $DIRS1
 do
    echo $DIR
 done

And if I run this script I get out put something like this :

Only
in
/opt/lampp/htdocs/scripts/www/:
file1
diff
-r
"/opt/lampp/htdocs/scripts/dev/File
1.txt"
"/opt/lampp/htdocs/scripts/www/File
1.txt"
0a1
>
sa
das
Only
in
/opt/lampp/htdocs/scripts/www/:
File
1.txt~
Only
in
/opt/lampp/htdocs/scripts/www/:
file
2
-
second

Actually I just want to file name where I find the diffrence so I can take perticular action either copy/delete.

Thanks

Upvotes: 0

Views: 1744

Answers (2)

Julian
Julian

Reputation: 2907

I don't think diff produces output which can be parsed easily for your purposes. It's possible to solve your problem by iterating over the files in the two directories and running diff on them, using the return value from diff instead (and throwing the diff output away).

The code to do this is a bit long, but here it is:

DIR1=./one # set as required
DIR2=./two # set as required

# Process any files in $DIR1 only, or in both $DIR1 and $DIR2
find $DIR1 -type f -print0 | while read -d $'\0' -r file1; do
    relative_path=${file1#${DIR1}/};
    file2="$DIR2/$relative_path"
    if [[ ! -f "$file2" ]]; then
        echo "'$relative_path' in '$DIR1' only"
        # Do more stuff here
    elif diff -q "$file1" "$file2" >/dev/null; then
        echo "'$relative_path' same in '$DIR1' and '$DIR2'"
        # Do more stuff here
    else
        echo "'$relative_path' different between '$DIR1' and '$DIR2'"
        # Do more stuff here
    fi
done

# Process files in $DIR2 only
find $DIR2 -type f -print0 | while read -d $'\0' -r file2; do
    relative_path=${file2#${DIR2}/};
    file1="$DIR1/$relative_path"
    if [[ ! -f "$file2" ]]; then
        echo "'$relative_path' in '$DIR2 only'"
        # Do more stuff here
    fi
done

This code leverages some tricks to safely handle files which contain spaces, which would be very difficult to get working by parsing diff output. You can find more details on that topic here.

Of course this doesn't do anything regarding files which have the same contents but different names or are located in different directories.

I tested by populating two test directories as follows:

echo "dir one only" > "$DIR1/dir one only.txt"
echo "dir two only" > "$DIR2/dir two only.txt"
echo "in both, same" > $DIR1/"in both, same.txt"
echo "in both, same" > $DIR2/"in both, same.txt"
echo "in both, and different" > $DIR1/"in both, different.txt"
echo "in both, but different" > $DIR2/"in both, different.txt"

My output was:

'dir one only.txt' in './one' only
'in both, different.txt' different between './one' and './two'
'in both, same.txt' same in './one' and './two'

Upvotes: 1

Juan Diego Godoy Robles
Juan Diego Godoy Robles

Reputation: 14955

Use -q flag and avoid the for loop:

diff -rq /opt/lampp/htdocs/scripts/dev/ /opt/lampp/htdocs/scripts/www/ 

If you only want the files that differs:

diff -rq /opt/lampp/htdocs/scripts/dev/ /opt/lampp/htdocs/scripts/www/ |grep -Po '(?<=Files )\w+'|while read file; do
   echo $file
done
   -q  --brief
          Output only whether files differ.

But defitnitely you should check rsync: http://linux.die.net/man/1/rsync

Upvotes: 0

Related Questions