【问题标题】:Compare two folders and copy/link unique entries to a new folder比较两个文件夹并将唯一条目复制/链接到新文件夹
【发布时间】:2012-03-21 14:26:09
【问题描述】:

如何将所有唯一文件从两个源文件夹复制到新的目标文件夹?

作为集合操作:如何计算两个文件夹之间的差异?

【问题讨论】:

  • (1) 这是递归的——你有目录树——还是只是查看每个文件夹的直接内容? (2) 一个源文件夹中是否可以存在与另一个源文件夹中的文件同名但内容不同的文件?如果是,它们被认为是不同的还是相同的?
  • (1) 是的,递归的。 (2)在我的情况下,内容不应该改变(只添加新文件)但是为了让答案对更多人更有用,如果它也能捕捉到不同的内容会很棒(另外,我的假设有一天可能是错误的)。

标签: bash scripting set-operations


【解决方案1】:

你可以试试这个:

cd <First Dir>
find . > /tmp/first.dat
cd <Second Dir>
find . > /tmp/second.dat
comm -23 /tmp/first.dat /tmp/second.dat | while read line; do cp <First Dir>/$line <New Dir> ; done
comm -13 /tmp/first.dat /tmp/second.dat | while read line; do cp <SecondDir>/$line <New Dir> ; done

【讨论】:

  • 这很好地扩展到“文件名存在,但内容不同”的场景。除了两个文件名列表之外,您还可以比较两个日期戳、文件大小、文件名元组、md5sum 或其他列表。
【解决方案2】:

要将foo/bar/中的所有文件复制到baz/,最简单的方法就是复制两者,然后让其中一个覆盖另一个:

cp --recursive foo/ baz/
cp --recursive bar/ baz/

如果你想更简洁一点,并且bar/复制foo/中存在的任何东西,你可以写:

cp --recursive foo/ baz/
( cd bar/
  find -exec bash -c ' if ! [[ -e ../foo/"{}" ]] ; then
                         cp "{}" ../baz/"{}"
                       fi
                     ' \;
)

您可以使用相同的方法在bar/ 中生成foo/ 中不存在的文件列表:

( cd bar/
  find -exec bash -c ' if ! [[ -e ../foo/"{}" ]] ; then
                         echo bar/"{}"
                       fi
                     ' \;
)

(或者您可以将echo bar/"{}" 更改为printf %s\0 bar/"{}" 以使用零值字节而不是换行符作为分隔符)。

或者,对于某些种类,您可以编写:

diff --old-line-format=%L --new-line-format= --unchanged-line-format= \
     <( cd foo/ ; find | sort ) <( cd bar/ ; find | sort )

它将cd foo/ ; find | sortcd bar/ ; find | sort 的输出作为输入文件传递给diff,并告诉diff 打印在第一个输入中 找到的行-文件并丢弃其他所有内容。 (注意:如果任何文件名包含换行符,这将中断。)

以上都没有比较不同文件的内容,只是因为我不确定如果它们不同应该怎么做。检查文件内容可以使用diff -r -q foo/ bar/ 作为起点,但我们该怎么做呢?

【讨论】:

    【解决方案3】:

    我确定还有其他方法(此处没有建议的额外文件操作),但这里有一个相对简单的方法来完成此操作。

    假设:
    A1) 只对文件夹的直接内容感兴趣。
    A2) 假定同名文件内容相同。

    1) 创建/使用一个空的临时目录 (tmp)
    2)将sourceDir1的内容复制到tmp
    3) 从 tmp
    中删除 sourceDir2 的内容 -- 现在你在 tmp 中拥有了 sourceDir1 的唯一文件
    4) 将 tmp 的内容移动到所需位置
    5) 重复步骤 2)-4) 交换 sourceDir1 和 sourceDir2 的角色

    注意事项:
    N1)您可以使用ls 列出文件(或目录),并将其重定向到文件(例如 s1.tmp)。然后可以通过grep比较其他文件夹的文件(目录)列表,看看当前文件(目录)是否在s1.tmp中。您可以使用此技术来计算要输入哪些目录进行递归处理(从而放松 A1)。
    N2)如果有问题的文件是文本文件,您可以使用 diff 来查看它们是否相同。如果是,请照常处理,否则适当处理相同文件名、不同内容的情况(例如,使用唯一扩展名将两个文件复制到目标目录以指示其来源——此处的逻辑取决于您的目标)。
    N3) 显然你也可以比较二进制文件,见stackoverflow#4013223superuser#135911

    【讨论】:

      【解决方案4】:

      起初,我认为我可以通过巧妙地使用 rsync 来解决这个问题,但没有任何效果。

      所以我的最终解决方案是一个小的Python script (gist)

      【讨论】:

        猜你喜欢
        • 2022-08-21
        • 1970-01-01
        • 1970-01-01
        • 2015-02-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-05-01
        相关资源
        最近更新 更多