比较2个目录并将差异复制到目录3

时间:2010-07-16 18:15:54

标签: linux comparison diff compare cp

我有三个目录。我想将directory1与directory2进行比较,然后获取这些更改/新文件并将它们复制到directory3。有没有一种简单的方法可以做到这一点,也许通过使用linux diff和cp命令?我对这些想法持开放态度。

谢谢!

安德鲁

5 个答案:

答案 0 :(得分:1)

我相信这是你想要的描述。

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

我不确定的一件事是,如果文件存在于dir1但不存在dir2,那么你想要的是什么。

答案 1 :(得分:1)

线程yonder很好地解决了你的问题,我认为!

从那里复制:

#!/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

答案 2 :(得分:1)

您也可以在没有bash脚本的情况下执行此操作:

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/

此解决方案使用sed从diff命令中删除所有其他文本,然后复制保留目录结构的文件。

答案 3 :(得分:0)

之前发布的两个答案帮助我开始,但没有让我一路走来。 thomax发布的解决方案非常接近但是我遇到了一个问题,即osx上的cp命令不支持--parents参数,所以我不得不在子文件夹的创建周围添加一些逻辑,这使得事情有点乱,我有重组一下。这就是我最终的结果:

#!/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

答案 4 :(得分:0)

考虑您在同一级别上dir1dir2dir3 内容设置如下:

    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

当你创建和应用这样的补丁:

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

然后您的内容为dir2dir3等效内容。

如果您的dir2dir1的级别不同 那么你必须编辑补丁中的文件名 这样你就有了相同数量的路径组件 在dir1dir2个文件名中。

您最好将dir2置于与dir1相同的水平, 因为没有优雅的方法(至少我知道)。

这里遵循“丑陋”的方式。

请注意dir2位于某些$BASEDIR 然后你应该将你的差异更新为来自$BASEDIR路径的dir2的修剪 像这样

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

然后您可以应用上面生成的路径。