Difference between two directories in Linux
我正在尝试查找存在于一个目录中但不存在于另一个目录中的文件,我尝试使用此命令:
1 | diff -q dir1 dir2 |
上述命令的问题是,它找到
我试图在
这是我的数据的一个小样本
1 2 3 4 5 | 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 |
我想到的另一个问题是如何在单个命令中找到
1 | 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 仅打印文件名。
这应该做的工作:
1 | diff -rq dir1 dir2 |
解释选项(通过diff(1)手册页):
-
-r - 递归比较找到的所有子目录。 -
-q - 仅输出文件是否不同。
1 | comm -23 <(ls dir1 |sort) <(ls dir2|sort) |
此命令将为您提供dir1中的文件,而不是dir2中的文件。
关于
进行此比较的一种好方法是将
例:
使用
1 | find /dir1/ -type f -exec md5sum {} \; > dir1.txt |
对另一个目录执行相同的过程:
1 | find /dir2/ -type f -exec md5sum {} \; > dir2.txt |
然后将结果两个文件与"diff"进行比较:
1 | diff dir1.txt dir2.txt |
当要比较的两个目录不在同一台机器中并且您需要确保两个目录中的文件相同时,此策略非常有用。
另一个做这项工作的好方法是使用git
1 | git diff --no-index dir1/ dir2/ |
最好的祝福!
Meld(http://meldmerge.org/)在比较目录和文件中做得很好。
vim的DirDiff插件是另一个用于比较目录的非常有用的工具。
1 | vim -c"DirDiff dir1 dir2" |
它不仅列出了目录中哪些文件不同,而且还允许您使用vimdiff检查/修改不同的文件。
对所有回复都不满意,因为大多数回复工作得非常慢并且为大型目录产生不必要的长输出,我编写了自己的Python脚本来比较两个文件夹。
与许多其他解决方案不同,它不会比较文件的内容。此外,它不会进入另一个目录中缺少的子目录。因此输出非常简洁,脚本运行速度很快。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | #!/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]) |
样品用法:
1 2 3 4 5 6 7 8 | 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 |
或者,如果您只想查看第一个目录中的文件:
1 2 3 4 | 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 |
附:如果您需要比较文件大小和文件哈希值以进行潜在更改,我在此处发布了更新的脚本:https://gist.github.com/amakukha/f489cbde2afd32817f8e866cf4abe779
另一个(大型目录可能更快)方法:
1 2 | $ find dir1 | sed 's,^[^/]*/,,' | sort > dir1.txt && find dir2 | sed 's,^[^/]*/,,' | sort > dir2.txt $ diff dir1.txt dir2.txt |
由于Erik的帖子,
这个答案通过添加
1 | git diff -D --no-index dir1/ dir2/ |
如果您使用
Binary files a/whatever and /dev/null differ
接受的答案还将列出两个目录中存在但具有不同内容的文件。要仅列出dir1中存在的文件,您可以使用:
1 | diff -r dir1 dir2 | grep 'Only in' | grep dir1 | awk '{print $4}' > difference1.txt |
说明:
- diff -r dir1 dir2:比较
- grep'仅在'中:获取包含'Only in'的行
- grep dir1:获取包含dir的行
这有点晚了但可能对某人有帮助。不确定diff或rsync是否只是以像这样的裸格式吐出文件名。感谢plhn提供了我在下面展开的优秀解决方案。
如果只需要文件名,那么只需以干净的格式复制所需的文件就很容易,可以使用find命令。
1 | comm -23 <(find dir1 | sed 's/dir1/\//'| sort) <(find dir2 | sed 's/dir2/\//'| sort) | sed 's/^\//dir1/' |
这假设dir1和dir2都在同一个父文件夹中。 sed只删除父文件夹,以便您可以将苹果与苹果进行比较。最后一个sed只是将dir1名称放回去。
如果你只想要文件:
1 | comm -23 <(find dir1 -type f | sed 's/dir1/\//'| sort) <(find dir2 -type f | sed 's/dir2/\//'| sort) | sed 's/^\//dir1/' |
同样对于目录:
1 | comm -23 <(find dir1 -type d | sed 's/dir1/\//'| sort) <(find dir2 -type d | sed 's/dir2/\//'| sort) | sed 's/^\//dir1/' |
这是用于打印同步两个目录的命令的bash脚本
1 2 3 | 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|" |
使用DIFF命令比较2个目录的简化方法
diff filename.1 filename.2 > filename.dat >>Enter
BLOCKQUOTE>
运行完成后打开filename.dat
你会看到:
仅在filename.1:filename.2中
仅在:directory_name:name_of_file1中
仅在:directory_Name:name_of_file2中
GNU
grep 可以使用选项-v 反转搜索。 这使得grep 报告不匹配的行。 这样您就可以从dir1 中的文件列表中删除dir2 中的文件。
1
2
3 grep -v -F -x -f <(find dir2 -type f -printf '%P
') <(find dir1 -type f -printf '%P
')选项
-F -x 告诉grep 在整行上执行字符串搜索。
kdiff3有一个很好的文件和目录的diff接口。
它适用于Windows,Linux和macOS。
您可以通过多种方式安装它:
- 视窗
- 64位安装程序
- 32位安装程序
- 苹果系统
- 二进制
- Homebrew Cask:
brew cask install kdiff3