精华内容
下载资源
问答
  • diff命令实现

    2021-09-20 21:43:02
    diff命令实现 diff是类UNIX系统下的一个重要的系统工具,用于比较两个文本文件的差异。 它有三种输出格式 先给大家看看两个用于比对的文件原文 file1: a e b a g h b g g file2: b c d g e g j h 格式一,普通格式...

    diff命令实现

    diff是类UNIX系统下的一个重要的系统工具,用于比较两个文本文件的差异。

    它有三种输出格式

    先给大家看看两个用于比对的文件原文

    file1:
    a
    e
    b
    a
    g
    h
    b
    g
    g
    
    file2:
    b
    c
    d
    g
    e
    g
    j
    h
    

    格式一,普通格式:

    $ diff file1 file2
    1,6d0
    < a
    < e
    < b
    < a
    < g
    < h
    7a2,3
    > c
    > d
    8a5
    > e
    9a7,8
    > j
    > h
    

    格式二,上下文格式:

    *** file1	2021-09-20 11:58:40.660690542 +0800
    --- file2	2021-09-20 11:58:50.369119254 +0800
    ***************
    *** 1,9 ****
    - a
    - e
    - b
    - a
    - g
    - h
      b
      g
      g
    --- 1,8 ----
      b
    + c
    + d
      g
    + e
      g
    + j
    + h
    

    格式三,合并格式:

    --- file1	2021-09-20 11:58:40.660690542 +0800
    +++ file2	2021-09-20 11:58:50.369119254 +0800
    @@ -1,9 +1,8 @@
    -a
    -e
    -b
    -a
    -g
    -h
     b
    +c
    +d
     g
    +e
     g
    +j
    +h
    

    实现原理LCS

    不管是哪一种输出,它们的核心原理是一致的

    diff的实现原理是最长公共子序列算法(LCS)

    接下来,以上面的字符串为例,对该算法进行解析

    aebaghbgg
    bcdgegjh
    

    首先,最长公共子序列算法和最长子串算法是不一样的两个算法。子串要求不仅先后顺序一致,还要前驱后继也一致,而最长公共子序列算法只要求先后顺序一致。

    例如,aebaaebaghbgg的一个子串,也是一个子序列,而abgg是其的一个子序列,而非子串

    公共子序列,就是同时是两个字符串的子序列的一段序列

    因此,最长公共子序列,就是两个字符串之间先后顺序一致的最长的一段序列

    例如,上面的两个字符串的一个最长公共子序列是egh

    a    e ba g   h bgg
    bcdg e    g j h
    

    知道了最长公共子序列后,我们就可以用最少的改动来使得两个文本一致

    现在,我们对LCS算法进行一个理论的推导。

    现在有两个字符串,一个字符串为p1p2p3p4...pm,另一个为q1q2q3q4...qn,设它们的一个最长子序列为r1r2r3r4...rk

    可以显然得到以下几个性质:

    1. k的取值一定在0~ max(m, n)之间,若两个字符串完全没有相同的字符,则其取值为0,若顺序完全相同,则取值为字符串的长度
    2. pm等于qn,那么,rk也一定等于pmqn。因为最长公共子序列是最长的,而r已经是一个最长公共子序列了
    3. pm不等于qn,那么有这几种情况:

    rk不等于pm,则r1r2r3...rkp1p2p3...p(m-1)q1q2q3...qn之间的最长公共子序列。举例,acdeabcd,它们的最长公共子序列显然是acd,第一个字符串的d后面的e就已经和最长公共子序列没关系了
    同理,rk不等于qn时,r1r2r3...rkp1p2p3...pmq1q2q3...q(n-1)之间的最长公共子序列

    很显然,这个性质可以用于推导递归公式

    我们设L(m, n)是字符串p1p2...pmq1q2...qn之间的最长子序列的长度
    m为0或者n为0的时候,即两个字符串有一个为空串,则显然没有最长公共子序列,L(0, 0)就是0

    m不等于0且n不等于0时,若pm等于pn则,L(m, n)=L(m-1, n-1)。继续拿上面的acdeabcd举例,现在它们的最长公共子序列是acd,当我们在后面再添加一个一样的字符时,例如n,则acdenabcdn的最长公共子序列就成了acdn,长度增长了1

    pm不等于pn,要么L(m-1, n)是最长的,要么L(m, n-1)是最长的

    因此,递推公式可以写为:

    L(m, n) = 
    	0, m == 0 || j == 0;
    	L(m - 1, m - 1) + 1, m > 0 && n > 0 && p[m] == q[n];
    	max(L(m, n - 1), L(m - 1, n)), m > 0 && n > 0 && p[m] != q[n]
    

    以最开始的

    aebaghbgg
    bcdgegjh
    

    举例

    m为0或n为0时,取值为0,有L(0...m, 0) = L(0, 0...n) = 0
    mn均不为0时,以L(1...3, 0...n)举例

    a != b, L(1, 1) = max(L(1, 0), L(0, 1)) = 0;
    a != c, L(1, 2) = max(L(1, 1), L(0, 2)) = 0;

    a != h, L(1, 8) = max(L(1, 7), L(0, 8)) = 0;

    e != b, L(2, 1) = max(L(2, 0), L(1, 1)) = 0;

    e == e, L(2, 5) = L(1, 4) + 1 = 1;
    e != g, L(2, 6) = max(L(1, 6), L(2, 5)) = 1;
    e != j, L(2, 7) = max(L(1, 7), L(2, 6)) = 1;

    b == b, L(3, 1) = L(2, 0) + 1 = 1;
    b != c, L(3, 2) = max(L(2, 2), L(3, 1)) = 1;

    将全部结果写作表格形式:

     | |0 1 2 3 4 5 6 7 8
     | | |b|c|d|g|e|g|j|h
    -|-------------------
    0| |0 0 0 0 0 0 0 0 0
     |-
    1|a|0 0 0 0 0 0 0 0 0
     |-
    2|e|0 0 0 0 0 1 1 1 1
     |-
    3|b|0 1 1 1 1 1 1 1 1
     |-
    4|a|0 1 1 1 1 1 1 1 1
     |-
    5|g|0 1 1 1 2 2 2 2 2
     |-
    6|h|0 1 1 1 2 2 2 2 3
     |-
    7|b|0 1 1 1 2 2 2 2 3
     |-
    8|g|0 1 1 1 2 2 3 3 3
     |-
    9|g|0 1 1 1 2 2 3 3 3
    

    可得这两个字符串的最长公共子序列长度为3

    但是,只知道长度是不够的,我们还需要获取对应的具体的子序列,才能知道哪些是需要更改的、哪些是维持原样就好的

    我们可以借助上面的表格进行逆推

    L(9, 8)=3,查看发现g != h,则它的值要么是从L(8, 8)继承来的,要么是从L(9, 7)
    因为L(8, 8) == L(9, 7) == 3,因此,任意选一个方向进行回溯都是可以的
    这里,我们统一选择向上的方向,即回溯至L(8, 8)
    g != h,重复上一步,回溯至L(7, 8)
    b != h,重复上一步,回溯至L(6, 8)
    h == h,因此,回溯序列的最后一位为h
    L(6, 8)的值来自于L(5, 7),因此,我们回溯至L(5, 7)
    g != j,回溯至L(5, 6)
    g == g,回溯至L(4, 5),回溯序列gh
    a != e,回溯至L(3, 5)
    b != e,回溯至L(2, 5)
    e == e,回溯至L(1, 4),回溯序列egh
    再回溯,就全是空串了
    因此,这两个字符串的一个最长公共子序列为egh

    这只是一个结果,如果我们选择另一个方向进行回溯,结果又会发生不同
    例如,我们若全部往左回溯,结果将是bgg,正好就是diff选择的结果

    实现

    diff的计算单元不是字符串,变成了行,我们需要比较每一个行之间的相似性

    这里,我认为最理想的做法是,计算出每一行的字符串哈希值,而不是使用字符串匹配函数进行比对

    因此,整个程序的大致流程为:

    1. 分别读取两个文件的内容,计算出行数、哈希值,并进行存储
    2. 使用LCS算法生成上述表格
    3. 进行回溯,标记不需要进行改动的行
    4. 进行输出

    数据结构设计

    因为我们的程序对数据的处理是以行为单位的,因此我们需要建立一个以行为基本单元的数据结构。而一个文件有多少行代码是未知的,因此,使用链表来表述再好不过了。

    这样,我们就可以设计出以下数据结构:

    struct lineblock {
    	int line;	// 行号
    	char *content;	// 内容
    	unsigned int hashval;
    	struct lineblock *next;
    };
    

    判断是否是二进制文件

    diff命令很显然只能用于处理文本文件而不能处理二进制文件,但是,在Linux中,文本文件和二进制文件的存储方式乃至文件属性都没有什么太大的差别。

    为了区分两种形式的文件,需要抓住它们之间特性的不同。文本文件中一般都是可读的字符,而二进制文件中通常都是一些乱码。我们可以利用这一点,任意读取一段长度的数据,判断其中是否存在不属于文本文件的字符存在。

    static void check_binary(char *src, int siz)
    {
    	int offset = 0;
    	assert(siz % BBS == 0);
    	while (offset < siz) {
    		if (*(int*) (src + offset) == 0) {
    		// Text files shouldn't have '\0' value, but it is common in binary files
    			fprintf(stderr, "Binary files %s and %s differ\n", Infname1, Infname2);
    			exit(EXIT_FAILURE);
    		}
    		offset += BBS;
    	}
    }
    

    这里我们判断是否存在连续四字节的\0的存在。(因为有些编辑器会往文本的开头添加一些控制字符,只判断是不是出现了一个单独的'\0'容易误判,连续4个\0就基本上可以锁定了)

    字符串哈希值计算

    这里,我使用了UNIX SYSTEM V中的字符串散列函数进行哈希值的计算

    static unsigned int hash(char *src)
    {
    	unsigned int h = 0;
    	unsigned int g;
    	while (*src != '\0') {
    		h = (h << 4) + *src++;
    		g = h & 0xF0000000;
    		if (g)
    			h ^= g >> 24;
    		h &= ~g;
    	}
    	return h;
    }
    

    它很快,并且很有效

    LCS算法接口设计

    我设计的接口长这样:

    int **lcs(int *vec1, int len1, int *vec2, int len2, int *retlen);
    

    巨多参数

    前四个参数不难理解,分别是传入的数组与数组长度,最后一个参数是返回的数组的长度。
    返回值是一个二维数组,用于标定最长公共子序列在每一个序列中的具体位置。

    我们将每一行计算出的哈希值放入一个数组中,传入这个接口,它就应当传回最长公共子序列在每一个数组中对应的下标,即文件中不需要进行改动的行号

    具体实现如下

    int **lcs(int *vec1, int len1, int *vec2, int len2, int *retlen)
    {
    	assert(vec1 != NULL && vec2 != NULL);
    
    	int **ret;
    	int retsiz;
    	int **tab;
    
    	tab = gen_lcstab(vec1, len1, vec2, len2);
    	retsiz = MAX(len1 + 1, len2 + 1);
    	ret = malloc(sizeof(int *) * 2);
    	ret[0] = malloc(sizeof(int) * retsiz);
    	ret[1] = malloc(sizeof(int) * retsiz);
    	// flash back
    	int i = len1, j = len2, pos = 0;
    	while (tab[i][j] > 0) {
    		if (vec1[i] == vec2[j]) {
    			ret[0][pos] = i;
    			ret[1][pos] = j;
    			i -= 1;
    			j -= 1;
    			pos++;
    			continue;
    		}
    		if (tab[i - 1][j] > tab[i][j - 1]) {
    			i -= 1;
    		} else {
    			j -= 1;
    		}
    	}
    	reverse(ret[0], pos);
    	reverse(ret[1], pos);
    	*retlen = pos;
    	return ret;
    }
    
    /**
    L(m, n) =
    	0,				m == 0 || j == 0;
    	L(m - 1, m - 1) + 1,		m > 0 && n > 0 && p[m] == q[n];
    	max(L(m, n - 1), L(m - 1, n)),	m > 0 && n > 0 && p[m] != q[n]
     */
    static int **gen_lcstab(int *vec1, int len1, int *vec2, int len2)
    {
    	int **tab = malloc(sizeof(int *) * (len1 + 1));
    	for (int i = 0; i < len1 + 1; i++) {
    		int size = sizeof(int) * (len2 + 1);
    		tab[i] = malloc(size);
    		memset(tab[i], 0, size);
    	}
    
    	for (int i = 1; i <= len1; i++) {
    		for (int j = 1; j <= len2; j++) {
    			if (vec1[i] == vec2[j]) {
    				tab[i][j] = tab[i - 1][j - 1] + 1;
    				continue;
    			}
    			if (tab[i - 1][j] > tab[i][j - 1]) {
    				tab[i][j] = tab[i - 1][j];
    			} else {
    				tab[i][j] = tab[i][j - 1];
    			}
    		}
    	}
    	return tab;
    }
    
    static void reverse(int *arr, int len)
    {
    	for (int i = 0; i < len / 2; i++) {
    		int tmp = arr[i];
    		arr[i] = arr[len - 1 - i];
    		arr[len - 1 - i] = tmp;
    	}
    }
    
    

    输出设计

    diff有多种输出格式,但是不论是哪一种输出格式,只要获取了上述算法得出的数据就可以很容易地实现。

    因为时间限制(我不想花好几天时间在完善这个Toy program上),我实现了diff的默认输出格式

    具体细节请查看代码:
    https://gitee.com/yingmanwumen/mydiff

    输出结果

    我们设计的diff和原版的diff的输出结果大体是一致的,但是在一些细节上会有所区别。这是不同的实现方法造成的。

    展开全文
  • 如何使用diff命令diff命令的语法如下:diff [OPTION]... FILES该diff命令可以以几种格式显示输出,其中最常用的是普通,上下文和统一格式。输出包含有关文件中哪些行必须更改以使它们变得相同的信息...

    diff是一个命令行实用程序,使您可以逐行比较两个文件。它还可以比较目录的内容。

    该diff命令最常用于创建一个补丁,其中包含可以使用该patch命令应用的一个或多个文件之间的差异。

    如何使用diff命令

    该diff命令的语法如下:

    diff [OPTION]... FILES

    该diff命令可以以几种格式显示输出,其中最常用的是普通,上下文和统一格式。输出包含有关文件中哪些行必须更改以使它们变得相同的信息。如果文件匹配,则不产生任何输出。

    要将命令输出保存到文件,请使用重定向运算符:

    diff file1 file2 > patch

    在本文中,我们将使用以下两个文件来解释diff命令的工作方式:

    文件1

    Ubuntu

    Arch Linux

    Debian

    CentOS

    Fedora

    文件2

    Kubuntu

    Ubuntu

    Debian

    Arch Linux

    Centos

    Fedora

    普通格式

    以最简单的形式,当diff命令在两个文本文件上运行且没有任何选项时,它将以正常格式生成输出:

    diff file1 file2

    输出将如下所示:

    0a1

    > Kubuntu

    2d2

    < Arch Linux

    4c4,5

    < CentOS

    ---

    > Arch Linux

    > Centos

    普通输出格式由一个或多个描述差异的部分组成。每个部分如下所示:

    change-command

    < from-file-line...

    ---

    > to-file-line...

    0a1,2d2和4c4,5是变化的命令。每个更改命令从左到右包含以下内容:

    第一个文件中的行号或行范围。

    一个特殊的更改字符。

    第二个文件中的行号或行范围。

    更改字符可以是以下之一:

    a -添加行。

    c -换行。

    d -删除行。

    更改命令后跟被删除()的完整行。

    让我们解释一下输出:

    0a1- 在file1的开头(第二行之后)添加第二个文件的行。

    > Kubuntu -如上所述,将第二行中的行添加到第一个文件中。

    2d2-删除2第一个文件中的行。在2后d符号表示,如果该行不删除,将上线出现2在第二个文件。

    < Arch Linux -删除的行。

    4c4,5-用第二个文件中的行替换(更改)5第一个文件中的行4-5。

    < CentOS -第一个文件中要替换的行。

    --- - 分隔器。

    > Arch Linux和> Centos-从所述第二文件中的行替换行中的第一个文件。

    上下文格式

    使用上下文输出格式时,该diff命令会在文件之间不同的行周围显示几行上下文。

    该-c选项指示diff以上下文格式产生输出:

    diff -c file1 file2

    输出:

    *** file12019-11-25 21:00:26.422426523 +0100

    --- file22019-11-25 21:00:36.342231668 +0100

    ***************

    *** 1,6 ****

    Ubuntu

    - Arch Linux

    Debian

    ! CentOS

    Fedora

    --- 1,7 ----

    + Kubuntu

    Ubuntu

    Debian

    ! Arch Linux

    ! Centos

    Fedora

    如果比较了文件,则输出以名称和时间戳开始,以及一个或多个描述差异的部分开始。每个部分如下所示:

    ***************

    *** from-file-line-numbers ****

    from-file-line...

    --- to-file-line-numbers ----

    to-file-line...

    from-file-line-numbers和to-file-line-numbers-行号或逗号分隔范围在第一和第二文件,分别线。

    from-file-line和to-file-line-不同的线和上下文的线:

    以两个空格开头的行是上下文行,这两个文件中的行相同。

    以减号(-)开头的行是第二个文件中不包含任何内容的行。第二个文件中缺少行。

    以加号(+)开头的行是对应于第一个文件中没有内容的行。第一个文件中缺少行。

    以感叹号(!)开头的行是在两个文件之间更改的行。!从第一个文件开始的每一行行在第二个文件中都有对应的匹配项。

    让我们解释输出中最重要的部分

    在此示例中,我们只有一节描述了差异。

    *** 1,6 ****并--- 1,7 ----告诉我们本节中包含的第一个文件和第二个文件中的行范围。

    行Ubuntu,Debian,Fedora,最后的空行是在这两个文件是相同的。这些行以双倍空格开头。

    行- Arch Linux从第一个文件对应于没有在第二个文件。尽管第二行中也存在此行,但是位置不同。

    行+ Kubuntu第二个文件对应于没有在第一个文件。

    行! CentOS从第一个文件,线! Arch Linux和! CentOS从第二个文件中的文件之间变化。

    默认情况下,上下文行的数量默认为三。要指定另一个数字,请使用-C(--contexts)选项:

    diff -C 1 file1 file2

    输出:

    *** file12019-11-25 21:00:26.422426523 +0100

    --- file22019-11-25 21:00:36.342231668 +0100

    ***************

    *** 1,5 ****

    Ubuntu

    - Arch Linux

    Debian

    ! CentOS

    Fedora

    --- 1,6 ----

    + Kubuntu

    Ubuntu

    Debian

    ! Arch Linux

    ! Centos

    Fedora

    输出以文件的名称和时间戳以及描述差异的一个或多个部分开始。每个部分采用以下形式:

    ***************

    @@ from-file-line-numbers to-file-line-numbers @@

    line-from-files...

    @@ from-file-line-numbers to-file-line-numbers @@ -本节中包含的第一个和第二个文件的行号或行范围。

    line-from-files -不同的线和上下文的线:

    以两个空格开头的行是上下文行,这两个文件中的行相同。

    以减号(-)开头的行是从第一个文件中删除的行。

    以加号(+)开头的行是从第一个文件添加的行。

    忽略大小写

    您可能在上面的示例中注意到,该diff命令默认情况下区分大小写。

    使用-i选项告诉diff忽略大小写:

    diff -ui file1 file2

    输出:

    --- file12019-11-25 21:00:26.422426523 +0100

    +++ file22019-11-25 21:00:36.342231668 +0100

    @@ -1,6 +1,7 @@

    +Kubuntu

    Ubuntu

    -Arch Linux

    Debian

    +Arch Linux

    CentOS

    Fedora

    写在最后

    比较文本文件之间的差异是Linux系统管理员最常见的任务之一。

    该diff命令可以逐行比较文件。有关更多信息,请使在您的终端中键入man diff命令来显示diff更多详细的用法。

    如有任何疑问,请在下面发表评论。

    展开全文
  • diff命令是linux上非常重要的工具,用于比较文件的内容,特别是比较两个版本不同的文件以找到改动的地方。diff在命令行中打印每一个行的改动。最新版本的diff还支持二进制文件。diff程序的输出被称为补丁(patch),...

    diff 命令是 linux上非常重要的工具,用于比较文件的内容,特别是比较两个版本不同的文件以找到改动的地方。diff在命令行中打印每一个行的改动。最新版本的diff还支持二进制文件。diff程序的输出被称为补丁 (patch),因为Linux系统中还有一个patch程序,可以根据diff的输出将a.c的文件内容更新为b.c。diff是svn、cvs、git等版本控制工具不可或缺的一部分。

    1.命令格式:

    diff[参数][文件1或目录1][文件2或目录2]

    2.命令功能:

    diff命令能比较单个文件或者目录内容。如果指定比较的是文件,则只有当输入为文本文件时才有效。以逐行的方式,比较文本文件的异同处。如果指定比较的是目录的的时候,diff 命令会比较两个目录下名字相同的文本文件。列出不同的二进制文件、公共子目录和只在一个目录出现的文件。

    3.命令参数:

    -  指定要显示多少行的文本。此参数必须与-c或-u参数一并使用。

    -a或--text  diff预设只会逐行比较文本文件。

    -b或--ignore-space-change  不检查空格字符的不同。

    -B或--ignore-blank-lines  不检查空白行。

    -c  显示全部内文,并标出不同之处。

    -C或--context  与执行"-c-"指令相同。

    -d或--minimal  使用不同的演算法,以较小的单位来做比较。

    -D或ifdef  此参数的输出格式可用于前置处理器巨集。

    -e或--ed  此参数的输出格式可用于ed的script文件。

    -f或-forward-ed  输出的格式类似ed的script文件,但按照原来文件的顺序来显示不同处。

    -H或--speed-large-files  比较大文件时,可加快速度。

    -l或--ignore-matching-lines  若两个文件在某几行有所不同,而这几行同时都包含了选项中指定的字符或字符串,则不显示这两个文件的差异。

    -i或--ignore-case  不检查大小写的不同。

    -l或--paginate  将结果交由pr程序来分页。

    -n或--rcs  将比较结果以RCS的格式来显示。

    -N或--new-file  在比较目录时,若文件A仅出现在某个目录中,预设会显示:Only in目录:文件A若使用-N参数,则diff会将文件A与一个空白的文件比较。

    -p  若比较的文件为C语言的程序码文件时,显示差异所在的函数名称。

    -P或--unidirectional-new-file  与-N类似,但只有当第二个目录包含了一个第一个目录所没有的文件时,才会将这个文件与空白的文件做比较。

    -q或--brief  仅显示有无差异,不显示详细的信息。

    -r或--recursive  比较子目录中的文件。

    -s或--report-identical-files  若没有发现任何差异,仍然显示信息。

    -S或--starting-file  在比较目录时,从指定的文件开始比较。

    -t或--expand-tabs  在输出时,将tab字符展开。

    -T或--initial-tab  在每行前面加上tab字符以便对齐。

    -u,-U或--unified=  以合并的方式来显示文件内容的不同。

    -v或--version  显示版本信息。

    -w或--ignore-all-space  忽略全部的空格字符。

    -W或--width  在使用-y参数时,指定栏宽。

    -x或--exclude  不比较选项中所指定的文件或目录。

    -X或--exclude-from  您可以将文件或目录类型存成文本文件,然后在=中指定此文本文件。

    -y或--side-by-side  以并列的方式显示文件的异同之处。

    --help  显示帮助。

    --left-column  在使用-y参数时,若两个文件某一行内容相同,则仅在左侧的栏位显示该行内容。

    --suppress-common-lines  在使用-y参数时,仅显示不同之处。

    4.使用实例:

    实例1:比较两个文件

    命令:

    输出:

    [[email protected] test3]# diff log2014.log log2013.log

    3c3

    ---

    > 2013-03

    8c8

    ---

    > 2013-08

    11,12d10

    说明:

    上面的“3c3”和“8c8”表示log2014.log和log20143log文件在3行和第8行内容有所不同;"11,12d10"表示第一个文件比第二个文件多了第11和12行。

    diff 的normal 显示格式有三种提示:

    a - add

    c - change

    d - delete

    实例2:并排格式输出

    命令:

    diff log2013.log log2014.log  -y -W 50

    输出:

    [[email protected] test3]# diff log2014.log log2013.log  -y -W 50

    2013-01                 2013-01

    2013-02                 2013-02

    2014-03               | 2013-03

    2013-04                 2013-04

    2013-05                 2013-05

    2013-06                 2013-06

    2013-07                 2013-07

    2013-07               | 2013-08

    2013-09                 2013-09

    2013-10                 2013-10

    2013-11               <

    2013-12               <

    [[email protected] test3]# diff log2013.log log2014.log  -y -W 50

    2013-01                 2013-01

    2013-02                 2013-02

    2013-03               | 2014-03

    2013-04                 2013-04

    2013-05                 2013-05

    2013-06                 2013-06

    2013-07                 2013-07

    2013-08               | 2013-07

    2013-09                 2013-09

    2013-10                 2013-10

    > 2013-11

    > 2013-12

    说明:

    “|”表示前后2个文件内容有不同

    “>”表示后面文件比前面文件多了1行内容

    实例3:上下文输出格式

    命令:

    diff log2013.log log2014.log  -c

    输出:

    [[email protected] test3]# diff log2013.log log2014.log  -c

    *** log2013.log 2012-12-07 16:36:26.000000000 +0800

    --- log2014.log 2012-12-07 18:01:54.000000000 +0800

    ***************

    *** 1,10 ****

    2013-01

    2013-02

    ! 2013-03

    2013-04

    2013-05

    2013-06

    2013-07

    ! 2013-08

    2013-09

    2013-10

    --- 1,12 ----

    2013-01

    2013-02

    ! 2014-03

    2013-04

    2013-05

    2013-06

    2013-07

    ! 2013-07

    2013-09

    2013-10

    + 2013-11

    + 2013-12[[email protected] test3]# diff log2014.log log2013.log  -c

    *** log2014.log 2012-12-07 18:01:54.000000000 +0800

    --- log2013.log 2012-12-07 16:36:26.000000000 +0800

    ***************

    *** 1,12 ****

    2013-01

    2013-02

    ! 2014-03

    2013-04

    2013-05

    2013-06

    2013-07

    ! 2013-07

    2013-09

    2013-10

    - 2013-11

    - 2013-12

    --- 1,10 ----

    2013-01

    2013-02

    ! 2013-03

    2013-04

    2013-05

    2013-06

    2013-07

    ! 2013-08

    2013-09

    说明:

    这种方式在开头两行作了比较文件的说明,这里有三中特殊字符:

    “+” 比较的文件的后者比前着多一行

    “-” 比较的文件的后者比前着少一行

    “!” 比较的文件两者有差别的行

    实例4:统一格式输出

    命令:

    diff log2014.log log2013.log  -u

    输出:

    [[email protected] test3]# diff log2014.log log2013.log  -u

    --- log2014.log 2012-12-07 18:01:54.000000000 +0800

    +++ log2013.log 2012-12-07 16:36:26.000000000 +0800

    @@ -1,12 +1,10 @@

    2013-01

    2013-02

    -2014-03

    +2013-03

    2013-04

    2013-05

    2013-06

    2013-07

    -2013-07

    +2013-08

    2013-09

    2013-10

    -2013-11

    -2013-12

    说明:

    它的第一部分,也是文件的基本信息:

    --- log2014.log 2012-12-07 18:01:54.000000000 +0800

    +++ log2013.log 2012-12-07 16:36:26.000000000 +0800

    "---"表示变动前的文件,"+++"表示变动后的文件。

    第二部分,变动的位置用两个@作为起首和结束。

    @@ -1,12 +1,10 @@

    前面的"-1,12"分成三个部分:减号表示第一个文件(即log2014.log),"1"表示第1行,"12"表示连续12行。合在一起,就表示下面是第一个文件从第1行开始的连续12行。同样的,"+1,10"表示变动后,成为第二个文件从第1行开始的连续10行。

    实例5:比较文件夹不同

    命令:

    diff  test3 test6

    输出:

    [[email protected] test]# diff test3 test6

    Only in test6: linklog.log

    Only in test6: log2012.log

    diff test3/log2013.log test6/log2013.log

    1,10c1,3

    ---

    > hostnamebaidu=baidu.com

    > hostnamesina=sina.com

    > hostnames=true

    diff test3/log2014.log test6/log2014.log

    1,12d0

    Only in test6: log2015.log

    Only in test6: log2016.log

    Only in test6: log2017.log

    说明:

    实例6:比较两个文件不同,并生产补丁

    命令:

    diff -ruN log2013.log log2014.log >patch.log

    输出:

    [[email protected] test3]# diff -ruN log2013.log log2014.log >patch.log

    总计 12

    -rw-r--r-- 2 root root  80 12-07 16:36 log2013.log

    -rw-r--r-- 1 root root  96 12-07 18:01 log2014.log

    -rw-r--r-- 1 root root 248 12-07 21:33 patch.log

    [[email protected] test3]# cat patc.log

    cat: patc.log: 没有那个文件或目录

    [[email protected] test3]# cat patch.log

    --- log2013.log 2012-12-07 16:36:26.000000000 +0800

    +++ log2014.log 2012-12-07 18:01:54.000000000 +0800

    @@ -1,10 +1,12 @@

    2013-01

    2013-02

    -2013-03

    +2014-03

    2013-04

    2013-05

    2013-06

    2013-07

    -2013-08

    +2013-07

    2013-09

    2013-10

    +2013-11

    说明:

    实例7:打补丁

    命令:

    输出:

    [[email protected] test3]# cat log2013.log

    2013-01

    2013-02

    2013-03

    2013-04

    2013-05

    2013-06

    2013-07

    2013-08

    2013-09

    2013-10[[email protected] test3]# patch log2013.log patch.log

    patching file log2013.log

    [[email protected] test3]# cat log2013.log

    2013-01

    2013-02

    2014-03

    2013-04

    2013-05

    2013-06

    2013-07

    2013-07

    2013-09

    2013-10

    2013-11

    说明:

    展开全文
  • 在比较文件的时候,通常会用基于GUI的软件。很少有人真正会为了这个目的使用命令行工具。...在本篇中,我们将通过一些实例来学习如何使用diff命令。Linux diff 命令让我们通过一些实际的例子理解diff命令。假设我...

    在比较文件的时候,通常会用基于GUI的软件。很少有人真正会为了这个目的使用命令行工具。虽然说使用命令行来比较文件/目录并不像一件小事儿那样容易,但是如果你是一个Linux使用者,那么我想你应该知道如何通过命令行比较文件,因为一旦使用了它,你会认为它绝对是一个快速的方法。

    04567898b7b3df22a6a0f98e460d7abb.png

    在本篇中,我们将通过一些实例来学习如何使用diff命令。

    Linux diff 命令

    让我们通过一些实际的例子理解diff命令。

    假设我们有两个文件(file1 和 file2):

    $ cat file1

    Hi,

    Hello,

    How are you?

    I am fine,

    Thank you.

    $ cat file2

    Hello,

    Hi,

    How are you?

    I am fine.

    你可以看见两个文件有些小的不同。现在,让我们看看diff命令如何找出两者的不同的。

    像这样运行diff命令:

    $ diff file1 file2

    1d0

    2a2

    >Hi,

    4,5c4

    ---

    >I am fine.

    你可以看见diff后面跟了两个文件的名字作为命令行的参数,并且它在输出中生成了差异比较。输出并不容易理解。理由是,这是被计算机使用的而不是为了人类。尽管如此,让我们一步步解码输出:

    注意 – 在下面的文本中,file1和file2将被当作旧文件和新文件。

    1d0

    这里,1d0这一行意味着旧文件的***行应该被删除(d)以使两个文件的***行同步。旧文件中需要被删除的行以'

    2a2

    >Hi,

    这里,2a2行意味着新文件中的第二行应该加到旧文件的第二行后。要添加的行显示在输出的下一行用'>'标记。

    4,5c4

    ---

    >I am fine.

    这里,4,5c4这一行意味着在旧文件中的4到5行现在已被改变并且需要用新文件中的第4行代替。添加和删除的行分别用'>'和'

    那么,来总结一下,

    首先diff命令的***个参数被视为旧文件而第二个参数被视为新文件。

    像1d0、2a2、4,5c4这种表达式可以用语法解码为 [旧文件的行号或者行的范围][行为][新文件的行号或者行的范围]。这里的'行为'可以是追加,删除或者改变替换。

    ''代表添加的行。

    除了文件外,diff命令还可以比较两个目录。让我们通过一个例子学习。

    这里是'new_dir'目录包含的内容:

    $ ls new_dir/

    file file2 frnd frnd1.cpp log1.txt log3.txt log5.txt

    file1 file name with spaces frnd1 frnd.cpp log2.txt log4.txt

    这是'orig_dir'目录含有的内容:(译注:原文为and here are the contents of a directory named ‘olddir’ ,其中'olddir'应为笔误。)

    $ ls orig_dir/

    file1 file name with spaces frnd1 frnd.cpp log2.txt log4.txt test

    file2 frnd frnd1.cpp log1.txt log3.txt log5.txt

    下面是diff命令执行后的输出:

    $ diff new_dir/ orig_dir/

    Only in new_dir/: file

    Only in orig_dir/: test

    你可以看到当diff命令被用来比较这两个目录时,很容易就会显示两个文件中缺失的文件。

    下面是一些在命令行下常用的选项:

    1. 用 -i 忽略大小写

    如果两个文件含有相同的文本但是大小写不同,diff命令仍会默认报告它不同。

    比如:

    $ cat file1

    HI

    $ cat file2

    hi

    $ diff file1 file2

    1c1

    ---

    >hi

    你可以看见diff命令在输出中报告了大小写不同。

    要去除这个默认行为,使用-i选项。

    以下是个例子:

    $ diff -i file1 file2

    $

    这样你可以看到没有生成输出,这是当两个文件相同时的默认行为。

    2. 用 -s 选项报告两个文件相同

    在例子1的后面,我们看到如果文件相同diff不会生成报告。虽然这个默认行为不错但是它仍可能会造成很大疑惑,特别对于新手而言。因此,如果你像样diff命令明确地报告两个文件不同,那么就使用-s命令选项。

    来举个例子:

    $ diff -is file1 file2

    Files file1 and file2 are identical

    你可以看到我加了-s选项在后面的例子中,这次diff命令会明确地报告两个文件是相同的。

    3. 使用 -b 忽略空格

    另外一个常用的是diff报告文件存在不同数量的空格。

    举例说明:

    $ cat file1

    Hi, how are you?

    $ cat file2

    Hi, how are  you?

    观察这两个文件***的不同是file2中'are'和'you'之间额外的空格。现在,当使用diff命令比较两个文件时,输出如下:

    $ diff file1 file2

    1c1

    ---

    >Hi, how are  you?

    因此你可以看到diff命令报告了不同。但是如果你想要忽略这些空格,使用 -b 选项。

    $ diff -b file1 file2

    $

    这样你可以看到由于-b选项,diff命令报告这两个文件是相同的。

    diff命令还提供了更多的命令行选项。阅读man page来获取完整的列表。

    【编辑推荐】

    【责任编辑:奔跑的冰淇淋 TEL:(010)68476606】

    点赞 0

    展开全文
  • Diff命令的功能 Linux中Diff命令的功能为逐行比较两个文本文件,列出其不同之处。它对给出的文件进行系统的检查,并显示出两个文件中所有不同的行,不要求事先对文件进行排序。2>语法 diff [options] file1 file2...
  • Linux diff命令详解

    2021-02-27 11:03:37
    下面良许小编就将Linux diff命令进行详述,希望对大家有所帮助。 diff 命令是以逐行的方式比较文本文件的异同处。如果该命令指定进行目录的比较,则将会比较该目录中具有相同文件名的文件,而不会对其子目录文件进行...
  • 大家好,我是良许。我们在平时工作的时候,经常要知道两个文件之间,以及同个文件不同版本之间有何异同点。在 Windows 下,有 beyond compare 这...diff命令是一个分析文件信息的命令,可以打印出文件之间的差异。它...
  • 如果你需要比较系统文件的内容,那么你就会是使用到diff命令,可找出文件之间相同的部分,下面小编就给大家详细介绍下Linux diff命令的用法。diff 命令是 linux上非常重要的工具,用于比较文件的内容,特别是比较两...
  • git diff命令详解

    2021-01-14 05:45:43
    diff里面a表示前面那个变量,b表示第二个变量HEAD commit版本Index staged版本a、查看尚未暂存的文件更新了哪些部分,不加参数直接输入git diff命令比较的是工作目录(Working tree)和暂存区域快照(index)之间的...
  • 本文介绍在Linux操作系统中使用Diff命令的方法,同时讲解普通/上下文/统一格式及忽略大小写知识。diff是一个命令行实用程序,可让你逐行比较两个文件,它还可以比较目录的内容。diff命令最常用于创建一个补丁,其中...
  • 摘要:下文讲述Linux中diff命令的功能说明,如下所示;diff命令功能:1.逐行逐行的对文本文件的不同之处进行对比2.当我们对比的为目录时,则diff会比较目录中相同文件名的文件,但不会比较子目录diff命令的语法格式:...
  • Linux shell diff命令

    2021-05-09 09:40:53
    -p若比较的文件为C语言的程序码文件时,显示差异所在的函数名称。-P , --unidirectional-new-file与-N类似,但只有当第二个目录包含了一个第一个目录所没有的文件时,才会将这个文件与空白的文件做比较。...
  • Linux命令之diff命令

    2021-06-08 17:32:52
    Linux diff命令用于比较文件的差异。diff以逐行的方式,比较文本文件的异同处。如果指定要比较目录,则diff会比较目录中相同文件名的文件,但不会比较其中子目录。diff的输出结果表明需要对一个文件做怎样的操作之后...
  • 本文将要为您介绍的是文件/目录对比:diff命令,教程操作步骤:命令格式diff [参数] [文件1或目录1] [文件2或目录2]Linux diff命令用于比较文件的差异。diff以逐行的方式,比较文本文件的异同处。如果指定要比较目录,...
  • 当一个文件有多个版本时候,或者更多复杂的文件,目录比较时,你会期望有一个比comm更有用的命令diff正是为此而生。全称:different file实例:文件1: v1.txthelloworld v1_echov1_diffv1_commshell is eas...
  • commands[0]="diff"; commands[1]=oldFileName; commands[2]=newFileName; log.info("command"+commands.toString()); try { Process proc=Runtime.getRuntime().exec(commands); InputStream in = proc....
  • Linux系统上的一个工具程式,...语法:diff [参数] [文件1或目录1] [文件2或目录2]补充说明:diff命令能比较单个文件或者目录内容。如果指定比较的是文件,则只有当输入为文本文件时才有效。以逐行的方式,比较文本...
  • 如果你需要比较系统文件的内容,那么你就会是使用到diff命令,可找出文件之间相同的部分,下面小编就给大家详细介绍下Linux diff命令的用法。diff 命令是 linux上非常重要的工具,用于比较文件的内容,特别是比较两...
  • 看到这个博客标题,可能很多朋友会觉得太简单了,不就直接使用Diff就行了吗?但是对于如Java源代码的比较,有一些额外需要考虑的因素:多余的空行不能算差别、Java源...怎么样达到这种需求呢,简单看一下Diff命令...
  • diff以逐行的方式,比较文本文件的异同处。如果指定要比较目录,则diff会比较目录中相同文件名的文件,但不会比较其中子目录 。语法格式:diff [参数] [目录]常用参数:-adiff预设只会逐行比较文本文件-b不检查空格...
  • 3.Normal模式 上面的部分我们说明了如何查看diff命令的结果,实际上对于上面的比较,我们使用的是diff命令的Normal模式,这也是diff命令的默认模式,也就是说diff两个文件的时候如果不加模式参数则是默认模式进行...
  • Linux diff 命令 文章目录Linux diff 命令简介输出结果解释实例实例1:比较两个文件实例2:并排格式输出常用参数 简介 Linux diff 命令用于比较文件的差异。 diff 以逐行的方式,比较文本文件的异同处。如果...
  • 文章目录1、git diff 命令说明2、比较工作区与暂存区中文件的差别3、比较暂存区与本地库中文件的差别4、总结git diff命令常见用法5、总结 1、git diff 命令说明 在commit操作之前,我们通常要确定一下自己在什么地方...
  • git diff 命令

    2020-12-19 08:22:11
    本文介绍git diff命令的几种不同的使用场景,可以比较工作区与最后一次commit的差异,可以比较staged状态的文件与最后一次commit的差异,还可以比较不同分支之间的差异。git diff命令,可以用来比较git工作区与仓库...
  • diff命令

    2021-05-24 10:39:39
    Linux diff命令用于比较文件的差异。 diff以逐行的方式,比较文本文件的异同处。如果指定要比较目录,则diff会比较目录中相同文件名的文件,但不会比较其中子目录。 参数: -<行数> 指定要显示多少行的文本...
  • diff 命令详解1.概述语法选项2.diff如何工作,如何理解diff的执行结果3.Normal模式4.Context模式5.Unified模式6.比较目录7.参数 -e 将比较的结果保存成一个ed脚本,之后ed程序可以执行该脚本文件,从而将file1修改成...
  • git diff命令

    2021-04-23 09:29:41
    注意:git diff查看的是还没有暂存起来的改动,而不是这次工作和上次提交之间的差异(因为可能你已经暂存过,之后又对文件进行了更改,diff显示的是这些改动) git diff --cached 是查看已经暂存起来的变化 2....

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 119,214
精华内容 47,685
关键字:

diff命令