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

发布于 2024-09-10 09:12:23 字数 132 浏览 5 评论 0原文

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

谢谢!

安德鲁

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

后知后觉 2024-09-17 09:12:23

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

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 中,您想要什么。

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.

情魔剑神 2024-09-17 09:12:23

线程

从那里复制的:

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

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
橘虞初梦 2024-09-17 09:12:23

您也可以不使用 bash 脚本来完成此操作:

diff -qr ./dir1 ./dir2 | sed -e 's/^仅在\(.*\): \(.*\)/\1\/\2/g' -e 's/ 和 \..*differ$//g' -e 's/^文件 //g' | xargs -I '{}' cp -Rf --parents '{}' ./dir3/

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

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.

梦里南柯 2024-09-17 09:12:23

之前发布的两个答案帮助我入门,但并没有让我一路走下去。 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

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
浪漫人生路 2024-09-17 09:12:23

假设您的 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
那么你应该更新你的 diff 以修剪 dir2 路径中的 $BASEDIR
像这样

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

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文