Linux|奇怪的知识| 不常用但非常有用的diff命令

简介: Linux|奇怪的知识| 不常用但非常有用的diff命令

前言:

Linux的常用命令应该不超过100个,因此,Linux的入门门槛是比较低的,但,高手和低手的区别在于一些其它的看起来很古怪的命令的认知和应用,比如,本文将要讲解的这个diff命令。

虽然,多会一些命令不会让你立刻成为一个Linux高手,但,从来高手都是比平常人站的更高,基础更加的牢固,因此眼界更远,能力更强,不是吗?

笑(^^^^_^^^^),因此,我现在也是万中无一的高手了。

OK, 不扯淡了,下面开始详细讲解这个非常有用的diff命令。

一,

diff命令的用途和历史

        OK,大概的历史得从c语言开始了,这个时间就很久远了,大概得从5  60年代开始了,好了,具体的细节我也是没有太多的记忆了,但,上个世纪80年代初,加州大学伯克利分校推出 BSD版本的 Unix 时,觉得 diff 的显示结果太简单,最好加入上下文,便于了解发生的变动。因此,推出了上下文格式的 diff,也就是优化了diff命令的输出,从这一点看,该命令是非常的古老了。

       diff命令是Unix系统下的内置命令,虽然非常的古老,但,该命令从来没有被删除,一直都存在于Unix系统内。因此,其实本文是旧酒装新瓶而已。

那么,该命令主要是比较文件(夹)的内容,并输出所比较的文件的内容哪些地方不同,或者哪些文件存在于文件夹,主要针对的是文本文件,二进制文件的比对工作用这个命令是不合适的,这里需要特别注意。

二,

diff命令的输出形式和常用参数

前文大略提了一下上下文格式的diff,那么,diff命令的输出到底有哪些呢?总共是四种格式:

正常格式(选项 --normal )
并列格式(选项 -y, --side-by-side)
上下文格式(选项 -C NUM, -c, --context[=NUM])
合并格式(选项 -U NUM, -u, --unified[=NUM])

常用参数:

c ,u, y,w,W,Z ,r

  • -a, --text
       所有的文件都视为文本文件来逐行比较
    -B, --ignore-blank-lines
       忽略插入删除空行引起的变化
    -b, --ignore-space-change
       忽略因空白符数量不同造成的差异
    -C NUM
    -c, --context[=NUM]
       使用上下文格式输出,显示异行处上下指定数量的行(默认为 3 行)
    --color[=WHEN]
        将输出着色;WHEN 可取值 never、always 或 auto(默认值)
    -D, --ifdef=NAME
       输出与 "#ifdef NAME" 不同的合并文件
    -d, --minimal
       改变算法找出一组更小的变更。这会使 diff 变慢
    -E, --ignore-tab-expansion
       忽略因 Tab 扩展引起的更改
    -e, --ed
       输出为一个有效的 ed 脚本
    -F, --show-function-line=RE
       显示匹配 RE 的前面的行
    --from-file=FILE1
       将 FILE 1 与所有文件进行比较;FILE 1 可以是一个目录
    --GTYPE-group-format=GFMT
       用组格式 GFMT 格式化类型为 GTYPE 的输入组
    --line-format=LFMT
       用格式 LFMT 格式化所有输入行
    --LTYPE-line-format=LFMT
        用行格式 LFMT 格式化类型为 LTYPE 的输入行
       上面三个选项和响应的格式提供了对输出的细粒度控制。
       行类型 LTYPE 可取值 old、new 或 unchanged,组类型 GTYPE 可取值 LTYPE 或 changed。
       组格式 GFMT 特含如下内容:
       %< FILE1 中的行
       %> FILE2 中的行
       %= FILE1 和 FILE2 中共有的行
       %[-][WIDTH][.[PREC]]{doxX}LETTER
           使用 printf 输出风格修饰 LETTER,LETTER 使用如下字母表示新组,下面的小写字母表示旧组
           F    首行行号
           L    尾行行号
           N    行数 = L-F+1
           E    等于 F-1
           M    等于 L+1
           %(A=B?T:E)
                 if A equals B then T else E
       行格式 LFMT  特含如下内容:
       %L    行的内容
       %l    行的内容,不包括任何尾随的换行符
       %[-][WIDTH][.[PREC]]{doxX}n
           使用 printf 风格修饰输入行号 n
       组格式 GFMT 和行格式 LFMT 共有的内容:
       %%            表示百分号 %
       %c'C'        表示大写字母 C
       %c'\OOO'    表示码值为八进制 000 的字符
       C            其他字符
    --help
       显示帮助信息并退出
    --horizon-lines=NUM
       保持共有前缀和后缀的 NUM 行
    -I, --ignore-matching-lines=RE
       忽略匹配正则表达式 RE 的行
    -i, --ignore-case
       忽略大小写
    --ignore-file-name-case
       比较文件名时忽略大小写
    -l, --paginate
       将结果交由 pr 程序来分页
    --label LABEL
       输出比较结果时使用 LABEL 代替文件名和时间戳
    --left-column
       只输出公共行的左列
    -N, --new-file
       将缺席文件视为空文件。在比较目录时,若文件 A 仅出现在某个目录中,预设会显示:Only in 目录:文件 A。若使用 -N 参数,则 diff 会将文件 A 与一个空白的文件比较
    -n, --rcs
       将比较结果以 RCS 的格式来显示
    --no-dereference
       不解析
    --no-ignore-file-name-case
       比较文件名时大小写敏感
    --normal
       使用正常格式输出比较结果。为默认输出格式
    -p, --show-c-function
       显示每个更改在哪个 C 函数中
    --palette=PALETTE
       当使用选项 --color 时,指定要使用的颜色。PALETTE 是使用冒号分隔的终端支持的能力列表
    -q, --brief
       仅报告文件是否相异,忽略差别的细节
    -r, --recursive
       当比较目录时,递归比较子目录
    -S, --starting-file=FILE
       当比较目录时,由 FILE 开始。这用于继续中断的比较
    -s, --report-identical-files
       当两个文件相同时报告
    --speed-large-files
       使用启发规则加速操作那些有许多离散的小差异的大文件
    --strip-trailing-cr
       去掉输入行尾的回车符 CR
    --suppress-common-lines
       在并列格式中不印出公共行
    -T, --initial-tab
       在每行前面加上 Tab 以便对齐
    -t, --expand-tabs
       在输出时将 Tab 扩展为空格
    --tabsize=NUM
       一个 Tab 表示 NUM(默认 8) 个空格
    --to-file=FILE2
       将所有文件与 FILE2 进行比较;FILE2 可以是一个目录
    -U NUM
    -u, --unified[=NUM]
       使用合并格式输出,输出 NUM(默认 3)行的统一上下文
    --unidirectional-new-file
       将缺席的第一批文件视为空文件
    -v, --version
       输出版本信息并退出
    -W, --width=NUM
       使用 -y 选项采用列格式输出时,指定栏宽。缺省为 130
    -w, --ignore-all-space
       在比较行的时候忽略空白符
    -y, --side-by-side
       使用并格式输出两列
    -Z, --ignore-trailing-space
        忽略行尾的空白符

三,

正常模式

本文将使用两个相似度比较高的文本文件做示例,文件内容如下:

A文件:

[root@centos61 media]# cat -A -n index.php
     1  <?php$
     2  /**$
     3   * Front to the WordPress application. This file doesn't do anything, but loads$
     4   * wp-blog-header.php which does and tells WordPress to load the theme.$
     5   *$
     6   * @package WordPress$
     7   */$
     8  $
     9  /**$
    10   * Tells WordPress to load the WordPress theme and output it.$
    11   *$
    12   * @var bool$
    13   */$
    14  define( 'WP_USE_THEMES', true );$
    15  hello World!!!!!~~$
    16  /** Loads the WordPress Environment and Template */$
    17  require( dirname( __FILE__ ) . '/wp-blog-header.php' );$

B文件:

[root@centos61 media]# cat -A -n index.php.back 
     1  <?php$
     2  /**$
     3   * Front to the WordPress application. This file doesn't do anything, but loads$
     4   * wp-blog-header.php which does and tells WordPress to load the theme.$
     5   *$
     6   * @package WordPress$
     7   */$
     8  $
     9  /**$
    10   * Tells WordPress to load the WordPress theme and output it.$
    11    *$
    12   * @var bool$
    13   */$
    14  define( 'WP_USE_THEMES', true );$
    15  $
    16  $
    17  $
    18  hello World!!!!!~~    $
    19  /** Loads the WordPress Environment and Template */$
    20  require( dirname( __FILE__ ) . '/wp-blog-header.php' );$

根据cat命令,我们肉眼观察,可以看到,是11行不同,B文件多了15  16 17 行, 18行的内容多了几个空格, 那么,diff命令会怎么说呢?

[root@centos61 media]# diff index.php index.php.back 
11c11
<  *
---
>   *
15c15,18
< hello World!!!!!~~
---
> 
> 
> 
> hello World!!!!!~~    

OK,这个输出很简单,大部分人应该是看不懂了。那么,具体的含义是什么呢?

1,11c11

这个表示的是A文件的11行改变了,对应的是B文件的11行

2,< 这个表示方向,也就是指的是A文件,  下面的 > 同样是表示方向,指的是B文件,因为,diff命令是  diff  A  B  嘛

3,--- 是第一部分不同,简单说就是一个分隔的,因此,前面四行表示 11行的A文件比B文件少一个空格

4,15c15,18 说的是 15行到18行两个文件不同,具体的不同是A的15行内容在18行了,并且B多了三个空行,是15-18

A文件修改成如下:

[root@centos61 media]# cat -A -n index.php
     1  <?php$
     2  /**$
     3   * Front to the WordPress application. This file doesn't do anything, but loads$
     4   * wp-blog-header.php which does and tells WordPress to load the theme.$
     5   *$
     6   * @package WordPress$
     7   */$
     8  $
     9  /**$
    10   * Tells WordPress to load the WordPress theme and output it.$
    11   *$
    12   * @var bool$
    13   */$
    14  define( 'WP_USE_THEMES', true );$
    15  hello World!!!!!~~$
    16  /** Loads the WordPress Environment and Template */$
    17  require( dirname( __FILE__ ) . '/wp-blog-header.php' );$

B文件修改成如下:

[root@centos61 media]# cat -A -n index.php.back 
     1  <?php$
     2  /**$
     3   * Front to the WordPress application. This file doesn't do anything, but loads$
     4   * wp-blog-header.php which does and tells WordPress to load the theme.$
     5   *$
     6   * @package WordPress$
     7   */$
     8  $
     9  /**$
    10   * Tells WordPress to load the WordPress theme and output it.$
    11    *$
    12   * @var bool$
    13   */$
    14  define( 'WP_USE_THEMES', true );$
    15  1111$
    16  $
    17  $
    18  hello World!!!!!~~    111$
    19  require( dirname( __FILE__ ) . '/wp-blog-header.php' );$
    20  1111111111111222222222$
    21  333333333333333333$

再次比较:

[root@centos61 media]# diff  index.php  index.php.back 
11c11
<  *
---
>   *
15,16c15,18
< hello World!!!!!~~
< /** Loads the WordPress Environment and Template */
---
> 1111
> 
> 
> hello World!!!!!~~    111
17a20,21
> 1111111111111222222222
> 333333333333333333

从整体的输出结果来看,通过数字和字母(例如11c11,15,16c15,18)分为了三个部分:

  • 11c11
    <  *
    ---
    >   *

这里是表示左边的文件的11行是 一个星,右边的文件的11行是一个空格+一个星

  • 15,16c15,18
    < hello World!!!!!~~
    < /** Loads the WordPress Environment and Template */
    ---
    > 1111
    >
    >
    > hello World!!!!!~~    111

这里表示左边的文件的15 16行的内容改变为右边的15-18行的四行

  • 17a20,21
    > 1111111111111222222222
    > 333333333333333333

这里表示左边的文件的17行后面添加右边的文件的20 21行内容即可,也就是 左边的文件加下面的内容(那些数字)到20 21行就会和右边的文件一样。

输出指出,11行,和15,18c15,16有改变,A文件比B文件少20和21行。那么,比较顺序改变一下,输出也会改变:

[root@centos61 media]# diff  index.php.back  index.php
11c11
<   *
---
>  *
15,18c15,16
< 1111
< 
< 
< hello World!!!!!~~    111
---
> hello World!!!!!~~
> /** Loads the WordPress Environment and Template */
20,21d17
< 1111111111111222222222
< 333333333333333333

20,21d17表示左边的文件删除下面的内容(那些数字),并只有17行就会和右边的文件一致

四,

上下文模式----Context 模式

添加参数c即为Context 模式,上下文模式大体如下(仍然使用上面修改后的示例文件):

[root@centos61 media]# diff  -c index.php  index.php.back 
*** index.php 2023-05-13 23:22:41.638404080 +0800
--- index.php.back  2023-05-14 00:23:43.814240804 +0800
***************
*** 8,17 ****
  /**
   * Tells WordPress to load the WordPress theme and output it.
!  *
   * @var bool
   */
  define( 'WP_USE_THEMES', true );
! hello World!!!!!~~
! /** Loads the WordPress Environment and Template */
  require( dirname( __FILE__ ) . '/wp-blog-header.php' );
--- 8,21 ----
  /**
   * Tells WordPress to load the WordPress theme and output it.
!   *
   * @var bool
   */
  define( 'WP_USE_THEMES', true );
! 1111
! 
! 
! hello World!!!!!~~    111
  require( dirname( __FILE__ ) . '/wp-blog-header.php' );
+ 1111111111111222222222
+ 333333333333333333

结果分析如下:

第一部分的两行,显示两个文件的基本情况:文件名和时间信息。

*** index.php    2023-05-13 23:22:41.638404080 +0800
--- index.php.back    2023-05-14 00:23:43.814240804 +0800

星号表示A文件,---表示B文件

第二部分

*** 8,17 ****表示A文件的8到17行

--- 8,21 ----表示B文件的8到21行

-    出现在前者,表示后者比前者少一行
+    出现在后者,表示后者比前者多一行
!    出现在两者,表示有差别的行

 

OK,上下文模式的输出比正常模式的输出好像要更容易看懂。

五,

合并模式----也即 Unified 模式

这种模式是简化了输出,尤其是两个文件相似度很高的情况下,会省去很多输出,输出更为简洁,但还是不直观,使用参数u即可

[root@centos61 media]# diff -u index.php index.php.back 
--- index.php 2023-05-13 23:22:41.638404080 +0800
+++ index.php.back  2023-05-14 00:23:43.814240804 +0800
@@ -8,10 +8,14 @@
 /**
  * Tells WordPress to load the WordPress theme and output it.
- *
+  *
  * @var bool
  */
 define( 'WP_USE_THEMES', true );
-hello World!!!!!~~
-/** Loads the WordPress Environment and Template */
+1111
+
+
+hello World!!!!!~~    111
 require( dirname( __FILE__ ) . '/wp-blog-header.php' );
+1111111111111222222222
+333333333333333333

输出说明:

第一部分,也是文件的基本信息。— 表示第一个文件,+++ 表示第二个文件。"---"表示变动前的文件,"+++"表示变动后的文件。

第二部分,@@包围的内容,其中 -8,10 表示输出的内容属于第一个文件的 8 至 10 行,+8,14 表示输出的内容属于第二个文件的 8 至 14行。
第三部分,为比较后合并的内容。减号 - 表示后者比前者少了该行,加号表示后者比前者多了该行。

参数u后面其实是有默认的3,也就是说输出默认的三行的上下文,如果想要更改,比如,只1行的上下文,命令为diff -u1 index.php index.php.back

[root@centos61 media]# diff -u1 index.php index.php.back
--- index.php    2023-05-13 23:22:41.638404080 +0800
+++ index.php.back    2023-05-14 00:23:43.814240804 +0800
@@ -10,3 +10,3 @@
 * Tells WordPress to load the WordPress theme and output it.
- *
+  *
 * @var bool
@@ -14,4 +14,8 @@
define( 'WP_USE_THEMES', true );
-hello World!!!!!~~
-/** Loads the WordPress Environment and Template */
+1111
+
+
+hello World!!!!!~~    111
require( dirname( __FILE__ ) . '/wp-blog-header.php' );
+1111111111111222222222
+333333333333333333


 

六,

并列模式

参数y结合-W 指定输出宽度(默认是130的间距,这个间距指的是左右的结果之间的距离)

[root@centos61 media]# diff -y -W 200  index.php index.php.back 
<?php                         <?php
/**                         /**
 * Front to the WordPress application. This file doesn't do anything, but loads        * Front to the WordPress application. This file doesn't do anything, but loads
 * wp-blog-header.php which does and tells WordPress to load the theme.          * wp-blog-header.php which does and tells WordPress to load the theme.
 *                           *
 * @package WordPress                      * @package WordPress
 */                          */
/**                         /**
 * Tells WordPress to load the WordPress theme and output it.            * Tells WordPress to load the WordPress theme and output it.
 *                           |    *
 * @var bool                         * @var bool
 */                          */
define( 'WP_USE_THEMES', true );                  define( 'WP_USE_THEMES', true );
hello World!!!!!~~                       |  1111
/** Loads the WordPress Environment and Template */              |
                           >
                           >  hello World!!!!!~~    111
require( dirname( __FILE__ ) . '/wp-blog-header.php' );             require( dirname( __FILE__ ) . '/wp-blog-header.php' );
                           >  1111111111111222222222
                           >  333333333333333333

说明:

  • "|"表示前后2个文件内容有不同
  • "<"表示后面文件比前面文件少了1行内容
  • ">"表示后面文件比前面文件多了1行内容

七,

比较目录

目录比较的时候比较简单,ONLY in  仅存在的意思

[root@centos61 media]# diff -r /etc/ /var/
Only in /etc/: adjtime
Only in /var/: adm
Only in /etc/: aliases
Only in /etc/: aliases.db
Only in /etc/: alternatives
Only in /etc/: anacrontab
Only in /etc/: asound.conf
Only in /etc/: audisp

总结:

根据实际的使用经验来说,diff命令推荐优先使用并列模式,最为直观,其次是普通模式,再次是上下文模式,最后是统一模式。

目录
相关文章
|
23小时前
|
关系型数据库 MySQL Linux
Linux命令systemctl详解
`systemctl`是Linux系统用于管理systemd服务的核心命令,它与systemd守护进程交互,实现启动、停止、重启服务及查看服务状态等功能。主要参数包括`start`、`stop`、`restart`、`status`、`enable`和`disable`等。例如,启动Apache服务使用`systemctl start httpd.service`,查看服务状态用`systemctl status &lt;service&gt;`。使用时需注意权限,服务名通常以`.service`结尾,但命令中可省略。最佳实践包括利用tab键补全、定期查看服务状态和合理配置服务自启。
|
23小时前
|
存储 安全 Linux
Linux命令sync详解
`sync`命令在Linux中用于将内存缓冲区的数据强制写入磁盘,保证数据持久性和一致性。它在关机、重启或重要文件操作前后使用,以防数据丢失。工作原理是强制将内存中的数据同步到磁盘,特点是阻塞式执行且通常无需参数。常见用法包括安全关机、数据备份和配置文件修改后确保更改生效。应注意,过度使用可能影响性能,应适时使用`fsck`检查文件系统一致性。
|
1天前
|
存储 算法 安全
Linux命令sum详解
`sum`命令在Linux中用于计算文件的校验和与磁盘块数,确保文件传输或存储时的完整性。它使用加法运算生成校验和,可与文件内容比较验证变化。支持不同算法(如CRC),能处理多个文件。基本用法包括:`sum file.txt`来计算校验和,`sum -c checksum.txt`来验证文件完整性。但要注意,更强的校验算法如MD5或SHA家族可能更适合安全性需求。结合`find`和`xargs`可用于目录的递归校验。定期校验和记录校验和是最佳实践。
|
1天前
|
安全 数据管理 Shell
Linux命令su详解
`su`命令在Linux中用于切换用户身份,常用于权限管理。它允许用户无须注销当前会话就切换到另一个用户,尤其是root。`su`有多种选项,如`-`或`--login`加载目标用户环境,`-c`执行指定命令后返回。使用时需注意权限安全,建议用`sudo`以减少风险。通过限制`/etc/pam.d/su`可加强访问控制。`su`在系统维护和数据管理中扮演角色,但不直接处理数据。
|
1天前
|
Unix Linux 数据处理
Linux命令stty详解
`stty`是Linux命令,用于设置和查看终端参数,如波特率、字符处理和控制字符。它直接与终端驱动交互,支持多种选项以适应不同的配置需求。例如,`stty -a`显示当前设置,`stty -echo`关闭回显,`stty 115200 cs8`调整波特率和字符大小。注意修改设置可能影响终端行为,建议先备份(`stty -g`)并谨慎操作。查阅手册页以获取详细信息。
|
1天前
|
安全 Linux 数据处理
Linux命令strip详解
`strip`命令在Linux中用于移除可执行文件和库的符号表及调试信息,减小文件大小,提升运行效率。它的工作原理是删除文件中包含的函数名、变量名等信息。主要参数包括`-s`(移除所有符号)、`-g`(仅移除调试信息)等。在应用时要注意文件备份,因为该操作不可逆。最佳实践是在发布版本中使用,并结合构建流程自动化。
|
1天前
|
安全 Linux 数据安全/隐私保护
Linux命令strings详解
`strings`是Linux工具,用于从二进制文件中提取可打印字符串,常用于文件分析、安全审计和逆向工程。它可以识别至少4个连续可打印字符的序列,并支持多种参数,如`-n`调整最小长度,`-f`显示文件名。示例用法包括`strings /bin/ls`和`strings -n 6 /usr/bin/uptime | grep GLIBC`。注意敏感信息泄露,结合其他命令可增强分析能力。
|
1天前
|
存储 监控 Linux
stdbuf命令在Linux中的深度解析
`stdbuf`是Linux工具,用于控制命令的stdin、stdout和stderr的缓冲模式。它可以设置为无缓冲、行缓冲或块缓冲,以优化数据处理和实时性。例如,`stdbuf -o0 cmd`禁用cmd的输出缓冲,`-oL`则按行缓冲。在需要实时监控或高效处理大量数据时,选择合适的缓冲模式至关重要。注意,过度使用无缓冲可能影响性能,并非所有系统都支持`stdbuf`。
|
1天前
|
存储 运维 安全
Linux命令stat:深入了解文件与文件系统状态
`stat`命令在Linux中用于显示文件和文件系统的详细状态,包括权限、大小、时间戳等。它通过读取inode获取信息,特点是显示全面、易用且支持多种参数,如`-c`自定义格式,`-f`查看文件系统状态,`-L`处理符号链接。例如,`stat example.txt`显示文件详情,`stat -c &quot;%n 的大小是 %s 字节&quot; example.txt`输出文件大小。理解`stat`有助于系统管理和故障排查。
|
1天前
|
监控 安全 Linux
Linux命令ssltap的深入解析与应用实践
`ssltap`是一个假想的Linux命令,用于模拟SSL/TLS流量分析。它捕获、解密(如果有密钥)并分析加密流量,提供实时监控、协议解析和安全审计。特点包括实时性、灵活性、可扩展性和安全性。示例用法包括捕获特定端口流量和实时监控会话状态。在实际操作中应注意私钥安全、性能影响及合规性,建议定期审计和自动化监控。