295

我正在尝试查找一个目录中存在但另一个目录中不存在的文件,我尝试使用此命令:

diff -q dir1 dir2

上述命令的问题是它找到了文件 indir1但不是 indir2以及文件 indir2但不是 in dir1

我试图在其中找到文件,dir1但不仅仅是在其中dir2

这是我的数据的一个小样本

dir1    dir2    dir3
1.txt   1.txt   1.txt
2.txt   3.txt   3.txt
5.txt   4.txt   5.txt
6.txt   7.txt   8.txt

我想到的另一个问题是如何在单个命令中找到文件,dir1但不能在dir2单个dir3命令中找到文件?

4

14 回答 14

390
diff -r dir1 dir2 | grep dir1 | awk '{print $4}' > difference1.txt

解释:

  • diff -r dir1 dir2显示哪些文件仅在 dir1 中,哪些仅在 dir2 中,以及两个目录中存在的文件的更改(如果有)。

  • diff -r dir1 dir2 | grep dir1 显示哪些文件只在 dir1

  • awk仅打印文件名。

于 2013-05-28T09:30:29.813 回答
139

这应该做的工作:

diff -rq dir1 dir2

选项解释(通过 diff(1)手册页):

  • -r- 递归比较找到的任何子目录。
  • -q- 仅输出文件是否不同。
于 2015-03-27T11:18:59.620 回答
50
comm -23 <(ls dir1 |sort) <(ls dir2|sort)

此命令将为您提供位于 dir1 而不是dir2 的文件。

关于<( )符号,您可以将其 google 为“进程替换”。

于 2014-07-11T10:17:58.373 回答
32

进行这种比较的一个好方法是使用findwith md5sum,然后使用 a diff

例子:

用于find列出目录中的所有文件,然后计算每个文件的 md5 哈希并将其通过管道传输到文件:

find /dir1/ -type f -exec md5sum {} \; > dir1.txt

对另一个目录执行相同的过程:

find /dir2/ -type f -exec md5sum {} \; > dir2.txt

然后将结果两个文件与“diff”进行比较:

diff dir1.txt dir2.txt

当要比较的两个目录不在同一台机器上并且您需要确保两个目录中的文件相等时,此策略非常有用。

完成这项工作的另一个好方法是使用git

git diff --no-index dir1/ dir2/

此致!

于 2017-01-09T19:48:24.680 回答
17

Meld ( http://meldmerge.org/ ) 在比较目录和其中的文件方面做得很好。

融合比较目录

于 2016-09-04T17:02:51.377 回答
13

vim 的DirDiff插件是另一个用于比较目录的非常有用的工具。

vim -c "DirDiff dir1 dir2"

它不仅列出了目录之间不同的文件,还允许您使用 vimdiff 检查/修改不同的文件。

于 2014-09-02T21:23:36.743 回答
11

对所有回复都不满意,因为它们中的大多数工作非常缓慢并且为大型目录产生不必要的长输出,我编写了自己的 Python 脚本来比较两个文件夹。

与许多其他解决方案不同,它不比较文件的内容。它也不会进入另一个目录中缺少的子目录。所以输出非常简洁,脚本运行速度很快。

#!/usr/bin/env python3

import os, sys

def compare_dirs(d1: "old directory name", d2: "new directory name"):
    def print_local(a, msg):
        print('DIR ' if a[2] else 'FILE', a[1], msg)
    # ensure validity
    for d in [d1,d2]:
        if not os.path.isdir(d):
            raise ValueError("not a directory: " + d)
    # get relative path
    l1 = [(x,os.path.join(d1,x)) for x in os.listdir(d1)]
    l2 = [(x,os.path.join(d2,x)) for x in os.listdir(d2)]
    # determine type: directory or file?
    l1 = sorted([(x,y,os.path.isdir(y)) for x,y in l1])
    l2 = sorted([(x,y,os.path.isdir(y)) for x,y in l2])
    i1 = i2 = 0
    common_dirs = []
    while i1<len(l1) and i2<len(l2):
        if l1[i1][0] == l2[i2][0]:      # same name
            if l1[i1][2] == l2[i2][2]:  # same type
                if l1[i1][2]:           # remember this folder for recursion
                    common_dirs.append((l1[i1][1], l2[i2][1]))
            else:
                print_local(l1[i1],'type changed')
            i1 += 1
            i2 += 1
        elif l1[i1][0]<l2[i2][0]:
            print_local(l1[i1],'removed')
            i1 += 1
        elif l1[i1][0]>l2[i2][0]:
            print_local(l2[i2],'added')
            i2 += 1
    while i1<len(l1):
        print_local(l1[i1],'removed')
        i1 += 1
    while i2<len(l2):
        print_local(l2[i2],'added')
        i2 += 1
    # compare subfolders recursively
    for sd1,sd2 in common_dirs:
        compare_dirs(sd1, sd2)

if __name__=="__main__":
    compare_dirs(sys.argv[1], sys.argv[2])

示例用法:

user@laptop:~$ python3 compare_dirs.py dir1/ dir2/
DIR  dir1/out/flavor-domino removed
DIR  dir2/out/flavor-maxim2 added
DIR  dir1/target/vendor/flavor-domino removed
DIR  dir2/target/vendor/flavor-maxim2 added
FILE dir1/tmp/.kconfig-flavor_domino removed
FILE dir2/tmp/.kconfig-flavor_maxim2 added
DIR  dir2/tools/tools/LiveSuit_For_Linux64 added

或者,如果您只想查看第一个目录中的文件:

user@laptop:~$ python3 compare_dirs.py dir2/ dir1/ | grep dir1
DIR  dir1/out/flavor-domino added
DIR  dir1/target/vendor/flavor-domino added
FILE dir1/tmp/.kconfig-flavor_domino added

PS如果您需要比较文件大小和文件哈希以了解潜在的变化,我在这里发布了一个更新的脚本:https ://gist.github.com/amakukha/f489cbde2afd32817f8e866cf4abe779

于 2018-01-16T10:25:12.613 回答
6

另一种(对于大型目录可能更快)方法:

$ find dir1 | sed 's,^[^/]*/,,' | sort > dir1.txt && find dir2 | sed 's,^[^/]*/,,' | sort > dir2.txt
$ diff dir1.txt dir2.txt

由于 Erik 的帖子,sed命令删除了第一个目录组件)

于 2016-06-20T08:29:38.600 回答
5

这个答案通过添加选项优化了@Adail-Junior 的建议之一,-D当被比较的两个目录都不是 git 存储库时,这很有帮助:

git diff -D --no-index dir1/ dir2/

如果您使用-D,那么您将看不到与以下内容的比较/dev/nulltext Binary files a/whatever and /dev/null differ

于 2018-11-05T23:16:53.100 回答
5

接受的答案还将列出两个目录中存在但内容不同的文件。要仅列出 dir1 中存在的文件,您可以使用:

diff -r dir1 dir2 | grep 'Only in' | grep dir1 | awk '{print $4}' > difference1.txt

解释:

  • diff -r dir1 dir2:比较
  • grep 'Only in':获取包含 'Only in' 的行
  • grep dir1 : 获取包含 dir 的行
于 2016-09-28T13:25:22.520 回答
5

这有点晚了,但可能会对某人有所帮助。不确定 diff 或 rsync 是否仅以像这样的裸格式吐出文件名。感谢 plhn 提供了我在下面扩展的那个很好的解决方案。

如果您只想要文件名以便以干净的格式复制所需的文件很容易,您可以使用 find 命令。

comm -23 <(find dir1 | sed 's/dir1/\//'| sort) <(find dir2 | sed 's/dir2/\//'| sort) | sed 's/^\//dir1/'

这假定 dir1 和 dir2 都在同一个父文件夹中。sed 只是删除父文件夹,因此您可以将苹果与苹果进行比较。最后一个 sed 只是将 dir1 名称放回去。

如果你只想要文件:

comm -23 <(find dir1 -type f | sed 's/dir1/\//'| sort) <(find dir2 -type f | sed 's/dir2/\//'| sort) | sed 's/^\//dir1/'

同样对于目录:

comm -23 <(find dir1 -type d | sed 's/dir1/\//'| sort) <(find dir2 -type d | sed 's/dir2/\//'| sort) | sed 's/^\//dir1/'
于 2015-08-14T13:27:50.010 回答
1

这是用于打印同步两个目录的命令的 bash 脚本

dir1=/tmp/path_to_dir1
dir2=/tmp/path_to_dir2
diff -rq $dir1 $dir2 | sed -e "s|Only in $dir2\(.*\): \(.*\)|cp -r $dir2\1/\2 $dir1\1|" |  sed -e "s|Only in $dir1\(.*\): \(.*\)|cp -r $dir1\1/\2 $dir2\1|" 
于 2018-09-07T21:47:30.863 回答
1

使用 DIFF 命令比较 2 个目录的简化方法

diff 文件名.1 文件名.2 > 文件名.dat >>Enter

运行完成后打开 filename.dat

你会看到: 仅在 filename.1:filename.2 仅在:directory_name:name_of_file1 仅在:directory_Name:name_of_file2

于 2016-07-25T14:59:34.550 回答
0

GNUgrep可以使用选项来反转搜索-v。这使得grep报告不匹配的行。通过这种方式,您可以dir2dir1.

grep -v -F -x -f <(find dir2 -type f -printf '%P\n') <(find dir1 -type f -printf '%P\n')

这些选项-F -x告诉grep对整行执行字符串搜索。

于 2018-08-09T07:21:36.027 回答