Compare 2 directories and copy differences to directory 3

雨燕双飞 提交于 2019-12-23 16:50:21

问题


I have three directories. I would like to compare directory1 with directory2, then take those changes/new files and copy them over to directory3. Is there an easy way to do this, maybe by using linux diff and cp commands? I'm open to ideas.

Thanks!

Andrew


回答1:


I believe this is what you want from your description.

for file in dir2/*; do
    file_in_dir1=dir1/$(basename ${file})
    if [ ! -e  ${file_in_dir1} ]; then
        # If the file in dir2 does not exist in dir1, copy
        cp ${file} dir3
    elif ! diff ${file} ${file_in_dir1}; then
        # if the file in dir2 is different then the one in dir1, copy
        cp ${file} dir3
    fi
done

One thing I wasn't sure about is what you wanted if a file exists in dir1 but not dir2.




回答2:


The thread yonder solves your problem quite nicely, I should think!

Copied from there:

#!/bin/bash

# setup folders for our different stages
DIST=/var/www/localhost/htdocs/dist/
DIST_OLD=/var/www/localhost/htdocs/dist_old/
DIST_UPGRADE=/var/www/localhost/htdocs/dist_upgrade/

cd $DIST

list=`find . -type f`

for a in $list; do
   if [ ! -f "$DIST_OLD$a" ]; then
        cp --parents $a $DIST_UPGRADE
      continue
   fi
   diff $a $DIST_OLD$a > /dev/null
   if [[ "$?" == "1" ]]; then
        # File exists but is different so copy changed file
        cp --parents $a $DIST_UPGRADE
   fi
done



回答3:


You can also do it without a bash script:

diff -qr ./dir1 ./dir2 | sed -e 's/^Only in\(.*\): \(.*\)/\1\/\2/g' -e 's/ and \..*differ$//g' -e 's/^Files //g' | xargs -I '{}' cp -Rf --parents '{}' ./dir3/

This solution removes all additional text from the diff command using sed, and then copies the files preserving the directory structure.




回答4:


The two previously posted answers helped me get started but didn't get me all the way there. The solution posted by thomax was really close but I ran into an issue where the cp command on osx doesn't support the --parents parameter so I had to add some logic around the creation of subfolders which made things a bit messy and I had to restructure a bit. Here's what I wound up with:

#!/bin/bash

# setup folders for our different stages
DIST=/var/www/localhost/htdocs/dist/
DIST_OLD=/var/www/localhost/htdocs/dist_old/
DIST_UPGRADE=/var/www/localhost/htdocs/dist_upgrade/

cd $DIST

find . -type f | while read filename
do

    newfile=false
    modified=false
    if [ ! -e  "$DIST_OLD$filename" ]; then
        newfile=true
        echo "ADD $filename"
    elif ! cmp $filename $DIST_OLD$filename &>/dev/null; then
        modified=true
        echo "MOD $filename"
    fi

    if $newfile || $modified; then

        #massage the filepath to not include leading ./
        filepath=$DIST_UPGRADE$(echo $filename | cut -c3-)

        #create folder for it if it doesnt exist
        destfolder=$(echo $filepath | sed -e 's/\/[^\/]*$/\//')
        mkdir -p $destfolder

        #copy new/modified file to the upgrade folder
        cp $filename $filepath
    fi
done



回答5:


Consider you have dir1, dir2 and dir3 on the same level with the content setup as below:

    mkdir dir1
    mkdir dir2
    echo 1 > dir1/a
    echo 1 > dir2/a
    echo 2 > dir1/b
    echo 3 > dir2/b
    echo 4 > dir2/c
    cp -r dir1 dir3

When you create and apply patch like this:

    diff -ruN dir1 dir2 | patch -p1 -d dir3

Then you have content of dir2 and dir3 equivalent.

If your dir2 is not at the same level as dir1 then you have to edit filenames in the patch so that you have equal amount of path components in both dir1 and dir2 filenames.

You should better put your dir2 to the same level as dir1, because there is no elegant way to do this (at least known to me).

Here follow an "ugly" way.

Consider your dir2 is located in some $BASEDIR then you should update your diff to trim of the $BASEDIR from dir2's path like this

    diff -ruN dir1 $BASEDIR/dir2 | \
    perl -slne 'BEGIN {$base =~ s/\//\\\//g; print $base}
                    s/\+\+\+ $base\//\+\+\+ /g; print'  \
    -- -base=$BASEDIR

And then you could apply the resulting path as above.



来源:https://stackoverflow.com/questions/3267735/compare-2-directories-and-copy-differences-to-directory-3

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!