查找一个目录中存在而另一个目录中不存在的文件

我试图找到一个目录中存在的文件,但不在另一个目录中,我尝试使用这个命令:

diff -q dir1 dir2

上面这个命令的问题是,它既找到了dir1中的文件,但不在dir2中,也找到了dir2中的文件,但不在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中的文件,而不是dir2dir3中的文件?

437693 次浏览
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只打印文件名。

comm -23 <(ls dir1 |sort) <(ls dir2|sort)

这个命令会给你dir1中的文件和dir2中的文件。

关于<( )符号,你可以谷歌它作为'进程替换'。

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

vim -c "DirDiff dir1 dir2"

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

这应该做的工作:

diff -rq dir1 dir2

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

  • -r -递归比较找到的任何子目录。
  • -q -只输出文件是否不同。

这有点晚,但可能会帮助到一些人。不确定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/'

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

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

sed命令删除第一个目录组件感谢Erik的帖子)

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

diff文件名。1文件名。2 > filename.dat >>输入

运行完成后打开filename.dat

,你会看到: 仅在文件名中。1: filename.2 仅在:directory_name: name_of_file1 仅限于:directory_Name: name_of_file2

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

Meld比较目录

接受的答案还将列出两个目录中存在但内容不同的文件。只列出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的行

进行这种比较的一个好方法是使用findmd5sum,然后使用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/

最好的问候!

我对所有的回复都不满意,因为它们中的大多数工作非常缓慢,并且对于大目录产生不必要的长输出,所以我编写了自己的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

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

GNU grep可以使用选项-v反向搜索。这使得grep报告不匹配的行。这样你就可以从dir1中的文件列表中删除dir2中的文件。

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

选项-F -x告诉grep在整行上执行字符串搜索。

这是用于打印同步两个目录的命令的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|"

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

git diff -D --no-index dir1/ dir2/
如果你使用-D,那么你将不会看到与/dev/null的比较: <代码>文本 二进制文件a/whatever和/dev/null不同 < /代码> < / p >