[ 知识是人生的灯塔,只有不断学习,才能照亮前行的道路 ]
描述:此命令用于统计文本中行数的、单词数、以及字节数,如果指定了超过一个文件,则还会打印一个总行数。此处的一个单词是指由空白字符分隔的长度大于零的字符序列,支持管道输入。
语法暗示
用法:wc [选项]... [文件]...
或:wc [选项]... --files0-from=F
wc【选项】【文件名】 # 字符/行数/字节所统计
# 参数
-c 统计字节数
-m 统计字符数(对于中文)
-l 统计行数
-w 统计单词数
-L 统计字符串长度
实际案例:
# 示例1.显示文件的内容信息
$ wc run.js
# 9 26 251 run.js
#'行数' '单词数' '字节数' '文件名'
# 示例2.中英文统计
tee site.txt <<'EOF'
weiyigeek.top
EOF
tee wechat.txt <<'EOF'
全栈工程师修炼指南
EOF
# 显示字节数(注意换行符也计算在其中)
wc -c site.txt # 14 site.txt
wc -c wechat.txt # 28 wechat.txt ,在 Rocky 9 实践中文占用三个字节
# 针对于中文字符(两个字节)
wc -m site.txt # 14 site.txt
wc -m wechat.txt # 10 wechat.txt ,在 Rocky 9 实践中对于中文字符(两个字符)
# 示例3.统计文件行数
wc -l /etc/passwd
# 43 /etc/passwd
# 示例4.统计文件字符长度(不含不可见字符)
wc -L site.txt
# 13 site.txt
# 示例5.联合使用返回df命令除首行之外的数据(了解即可,实际shell编程中很少这么写)
df | tail -n $(echo `df | wc -l`-1|bc)
devtmpfs 4096 0 4096 0% /dev
tmpfs 886560 0 886560 0% /dev/shm
tmpfs 354628 17788 336840 6% /run
/dev/mapper/rl-root 69955584 2426260 67529324 4% /
/dev/mapper/rl-home 33099776 264000 32835776 1% /home
/dev/sda2 983040 256384 726656 27% /boot
/dev/sda1 613160 7144 606016 2% /boot/efi
tmpfs 177312 0 177312 0% /run/user/0
描述:比较给定的两个文件不同之处,并以所在行的形式进行显示;默认是以逐行的方式进行比较文本文件的异同处,比较两个文件的内容 (源文件 和 目标文件),如果使用“-”代替“文件”参数,则要比较的内容将来自标准输入。
基础语法
用法:diff [选项]... 文件列表
# 参数:
# 长选项的必需参数也是相应短选项的必需参数。
--normal 以正常的 diff 方式输出 (默认)
-q, --brief 只有在文件不同时报告
-s, --report-identical-files 当两个一样时仍然显示结果
-c, -C NUM, --context[=NUM] 同时输出 NUM 行(默认为 3 行)的复制上下文内容
-u, -U 数量, --unified[=数量] 输出 <数量>(默认为 3)行一致化上下文 (常用)
-e, --ed 以 ed script 方式输出
-n, --rcs 以 RCS diff 格式输出
-y, --side-by-side 以两栏的格式输出
-W, --width=数量 每行显示最多 <数量>(默认 130)个字符
--left-column 当有两行相同时只显示左边栏的一行
--suppress-common-lines 当有两行相同时不显示
-p, --show-c-function 显示每个变更位于哪个 C 函数中
-F, --show-function-line=正则 显示匹配给定<正则>表达式的最近一行
--label 标签 使用给定<标签>替代文件名和时间戳
(可以重复)
-t, --expand-tabs 将输出中的 tab 转换成空格
-T, --initial-tab 每行先加上 tab 字符,使 tab 字符可以对齐
--tabsize=数字 TAB 格的宽度,默认为 8 个打印列宽
--suppress-blank-empty 在空的输出行之前去除空白或制表符
-l, --paginate 将输出送至 “pr” 指令来分页
-r, --recursive 连同所有子目录一起比较
--no-dereference 不要跟随符号链接
-N, --new-file 不存在的文件以空文件方式处理
--unidirectional-new-file 若第一文件不存在,以空文件处理
--ignore-file-name-case 忽略文件名大小写的区别
--no-ignore-file-name-case 不忽略文件名大小写的区别
-x, --exclude=模式 排除匹配 <模式> 的文件
-X, --exclude-from=文件 排除所有匹配在<文件>中列出的模式的文件
-S, --starting-file=文件 当比较目录時,由<文件>开始比较
--from-file=文件1 将<文件1>和操作数中的所有文件/目录作比较;
<文件1>可以是目录
--to-file=文件2 将操作数中的所有文件/目录和<文件2>作比较;
<文件2>可以是目录
-i, --ignore-case 忽略文件内容大小写的区别
-E, --ignore-tab-expansion 忽略由制表符宽度造成的差异
-Z, --ignore-trailing-space 忽略每行末端的空格
-b, --ignore-space-change 忽略由空格数不同造成的差异
-w, --ignore-all-space 忽略所有空格
-B, --ignore-blank-lines 忽略任何因空行而造成的差异
-I, --ignore-matching-lines=正则 若某行完全匹配 <正则>,则忽略由该行造成的差异
-a, --text 所有文件都以文本方式处理
--strip-trailing-cr 去除输入内容每行末端的回车(CR)字符
-D, --ifdef=名称 输出的内容以 ‘#ifdef <名称>’ 方式标明差异
--GTYPE-group-format=GFMT 以 GFMT 格式处理 GTYPE 输入行组
--line-format=LFMT 以 LFMT 格式处理每一行资料
--LTYPE-line-format=LFMT 以 LFMT 格式处理 LTYPE 输入的行
这些格式化选项提供对 diff 输出的精细控制,从而泛化 -D/--ifdef。
LTYPE 可以是 “old”、“new” 或 “unchanged”。GTYPE 可以是 LTYPE 的选择
或是 “changed”。
(仅)GFMT 可包括:
%< 该组中每行属于<文件1>的差异
%> 该组中每行属于<文件2>的差异
%= 该组中同时在<文件1>和<文件2>出现的每一行
%[-][宽度][.[精确度]]{doxX}字符 以 printf 格式表示该<字符>代表的内容
大写<字符>表示属于新的文件,小写表示属于旧的文件。<字符>的意义如下:
F 行组中第一行的行号
L 行组中最后一行的行号
N 行数 ( =L-F+1 )
E F-1
M L+1
%(A=B?T:E) 如果 A 等于 B 那么 T 否则 E
(仅)LFMT 可包括:
%L 该行的内容
%l 该行的内容,但不包括结束的换行符
%[-][宽度][.[精确度]]{doxX}n 以 printf 格式表示的输入行号
GFMT 或 LFMT 都可包括:
%% %
%c'C' 单个字符 C
%c'\OOO' 八进制码 OOO 所代表的字符
C 字符 C(处上述转义外的其他字符代表它们自身)
-d, --minimal 尽可能找出最小的差异集
--horizon-lines=数量 保持<数量>行的一致前后缀
--speed-large-files 假设文件十分大而且文件中含有许多微小的差异
--color[=何时] 给输出上色;“何时”可以是“never”(从不)、
“always”(总是)或“auto”(自动,默认)
--palette=调色板 在 --color 选项启用时使用的颜色;<调色板>参数应当是
一个冒号分隔的列表以提供 terminfo capabilities 信息
特殊字符含义:
实际案例:
tee user1.txt <<EOF
weiyigeek
weiyi
全栈工程师
EOF
tee user2.txt <<EOF
weiyigeek
Weiyigeeker
全栈工程师修炼指南
唯一
EOF
# 示例1.将目录下的 user1.txt 文件与 user2.txt 文件进行比较
diff user1.txt user2.txt
2,3c2,4
< weiyi
< 全栈工程师
---
> Weiyigeeker
> 全栈工程师修炼指南
> 唯一
# 示例2.递归比较两个文件夹的不同
diff -r web/ html/
weiyigeek.top-diff命令示例图
# 示例3.将补定文件进行输入到新文件夹中
# 从效果来看事是将两个文件的不同之处都输出 -3,5 代表 删除两个字符, +3,5代表添加两个字符
diff -ruN test1.rb,test1.rb
diff -ruN test.rb test1.rb > test.diff # 此处,输出文件被称为补丁(patch),可以使用patch命令将文件内容更新
# 示例4.以并列输出格式展示两个文件的不同
diff -y t1.txt t2.txt
diff -y -W 40 t1.txt t2.txt # 并列输出格式下控制宽度
this is a text! this is aaa text!
# 示例5.以上下文输出格式展示两个文件的不同
diff -c t1.txt t2.txt
diff -c t1.txt t2.txt
#*代表t1.txt - 代表t2.txt - !标注差异行
# 示例6.以统一输出格式展示两个文件的不同
--- t1.txt 2018-06-23 21:44:15.171207940 +0800 #-代表t1.txt
+++ t2.txt 2018-06-23 21:44:54.987207910 +0800 #+代表t2.txt
#//-代表前面的文件比后面的文件多一行,+代表后面的文件比前面的文件多一行,一般一一对应
温馨提示:
源文件 是一个目录和 目标文件 不是(目录)
, diff 会比较在 源文件(目录) 里的文件的中和目标文件同名的(文件)
, 反过来也一样非目录文件不能是 - .描述:此命令可以根据diff命令生成的补丁文件对源文件进行更新修改,从而更新修改到指定文件,特别注意此命令最小化安装时没有它,需要手动安装patch命令。
语法参数
Usage: patch [OPTION]... [ORIGFILE [PATCHFILE]]
# 参数
-b:自动备份改变的文件。
常用示例:
示例1.使用 patch 命令将补丁文件应用到源文件(恢复),根据不同之处进行恢复。
# 安装 patch 命令
yum install patch
# 生成 patch 命令使用的补丁文件()
diff -u user1.txt user2.txt > user.patch
--- user1.txt 2024-09-20 23:07:48.864277459 +0800
+++ user2.txt 2024-09-20 23:07:48.866277448 +0800
@@ -1,3 +1,4 @@
weiyigeek
-weiyi
-全栈工程师
+Weiyigeeker
+工作工程师修炼指南
+唯一
rm -rf user2.txt
# 根据补丁文件恢复user2.txt文件
patch -b user1.txt user.patch
# patching file user1.txt
# 结果查看
[root@Rocky9 ~ 192.168.228.128 23:30]# cat user1.txt.orig (源)
weiyigeek
weiyi
全栈工程师
[root@Rocky9 ~ 192.168.228.128 23:30]# cat user1.txt (根据patch恢复的user2.txt)
weiyigeek
Weiyigeeker
工作工程师修炼指南
唯一
描述:源程序文件(通常是纯文本文件)比较和合并工具一直是软件开发过程中比较重要的组成部分,现在市场上很多功能很强大的专用比较和合并工具:
例如,BeyondCompare 很多IDE或者软件配置管理系统,比如Eclipse, Rational ClearCase都提供了内建的功能来支持文件的比较和合并;
当远程工作在 Unix/Linux 平台上的时候,恐怕最简单而且到处存在的就是命令行工具,比如diff(可惜diff的功能有限,使用起来也不是很方便);
Vim 提供的diff模式通常称作vimdiff作为命令行的比较工具,我们仍然希望能拥有简单明了的界面,可以使我们能够对比较结果一目了然;我们还希望能够在比较出来的多处差异之间快速定位,希望能够很容易的进行文件合并;
由于,vimdiff 命令依赖于vim、diff命令的,相当于vim -d
命令,所以vimdiff中快捷键与vim有共通的地方;
语法参数:
用法: vim [参数] [文件 ..] 编辑指定的文件
或: vim [参数] - 从标准输入(stdin)读取文本
或: vim [参数] -t tag 编辑 tag 定义处的文件
或: vim [参数] -q [errorfile] 编辑第一个出错处的文件
参数:
-- 在这以后只有文件名
-v Vi 模式 (同 "vi")
-e Ex 模式 (同 "ex")
-E Improved Ex mode
-s 安静(批处理)模式 (只能与 "ex" 一起使用)
-d Diff 模式 (同 "vimdiff")
-y 容易模式 (同 "evim",无模式)
-R 只读模式 (同 "view")
-Z 限制模式 (同 "rvim")
-m 不可修改(写入文件)
-M 文本不可修改
-b 二进制模式
-l Lisp 模式
-C 兼容传统的 Vi: 'compatible'
-N 不完全兼容传统的 Vi: 'nocompatible'
-V[N][fname] Be verbose [level N] [log messages to fname]
-D 调试模式
-n 不使用交换文件,只使用内存
-r 列出交换文件并退出
-r (跟文件名) 恢复崩溃的会话
-L 同 -r
-A 以 Arabic 模式启动
-H 以 Hebrew 模式启动
-T <terminal> 设定终端类型为 <terminal>
--not-a-term Skip warning for input/output not being a terminal
--ttyfail Exit if input or output is not a terminal
-u <vimrc> 使用 <vimrc> 替代任何 .vimrc
--noplugin 不加载 plugin 脚本
-p[N] 打开 N 个标签页 (默认值: 每个文件一个)
-o[N] 打开 N 个窗口 (默认值: 每个文件一个)
-O[N] 同 -o 但垂直分割
+ 启动后跳到文件末尾
+<lnum> 启动后跳到第 <lnum> 行
--cmd <command> 加载任何 vimrc 文件前执行 <command>
-c <command> 加载第一个文件后执行 <command>
-S <session> 加载第一个文件后执行文件 <session>
-s <scriptin> 从文件 <scriptin> 读入正常模式的命令
-w <scriptout> 将所有输入的命令追加到文件 <scriptout>
-W <scriptout> 将所有输入的命令写入到文件 <scriptout>
-x 编辑加密的文件
--startuptime <file> Write startup timing messages to <file>
-i <viminfo> 使用 <viminfo> 取代 .viminfo
--clean 'nocompatible', Vim defaults, no plugins, no viminfo
常用使用
# 示例1.分别用 vimdiff 和 vim -d 打开两个对比文件,效果相同
vimdiff f1.txt f2.txt
vim -d f1.txt f2.txt
# 示例2.在vim编辑器分割窗口命令来启动diff模式:
vim FILE_LEFT
:vertical diffsplit FILE_RIGHT # 底行模式(垂直排列)
# 同时操作两个文件在比较和合并告一段落之后,可以用下列命令对两个文件同时进行操作。
# 比如同时退出:
:qa (quit all)
# 如果希望保存全部文件:
:wa (write all)
# 或者是两者的合并命令,保存全部文件,然后退出:
:wqa (write, then quit all)
# 如果在退出的时候不希望保存任何操作的结果:
:qa! (force to quit all)
温馨提示:上述两个文件中都存在但是包含差异的行显示为粉色背景,引起差异的文字用红色背景加以突出。
weiyigeek.top-vimdiff命令示例
示例2.vimdiff模式下行间光标移动
# 可看左右两侧的屏幕滚动是同步的,这是因为"scrollbind"选项被设置了的结果,vim会尽力保证两侧文件的对齐:
ctrl+w #光标左右切换两个文件之间来回跳转
:set noscrollbind # 如果不想要这个特性,可以设置
# 使用快捷键在各个差异点之间快速移动。跳转到下一个差异点:
]c #下一个
[c #上一个
如果在命令前加上数字的话,可以跳过一个或数个差异点从而实现跳的更远,比如如果在位于第一个差异点的行输入"2]c",将越过下一个差异点,跳转到第三个差异点。
# 如果希望交换两个窗口的位置或者希望改变窗口的分割方式可以使用下列命令:
# 其中1和3两个操作会把窗口改成水平 hT 分割方式
1. Ctrl - w - K(把当前窗口移到最上边)
2. Ctrl - w - H(把当前窗口移到最左边)
3. Ctrl - w - J(把当前窗口移到最下边)
4. Ctrl - w - L(把当前窗口移到最右边)
示例3.vimdiff 模式下的文件合并,以消除差异。
#如果希望把一个差异点中当前文件的内容复制到另一个文件里,可以使用命令模式
dp | (diff "put")
#如果希望把另一个文件的内容复制到当前行中,可以使用命令
do | (diff "get",之所以不用dg,是因为dg已经被另一个命令占用了)
#在修改一个或两个文件之后,vimdiff会试图自动来重新比较文件,来实时反映比较结果。但是也会有处理失败的情况,这个时候需要手工来刷新比较结果:
:diffupdate
如果希望撤销修改可以和平常用vim编辑一样直接<ESC>, u,但是要注意一定要将光标移动到需要撤销修改的文件窗口中。
# 1.先指定范围1-100行,再用当前窗口的不同处替换到另外一个窗口:
输入"1,100 diffpu".或输入"1,100 diffput".
输入"1,100 diffg 3".或输入"1,100 diffget 3". #这里,在diffg后面指定缓冲名字
# 这里等同于dp不过指定了范围,如果有缓冲还可在diffpu后面指定缓冲名字。
2.先指定范围1-100行,再用另外一个窗口的不同处替换当前:
# 输入"1,100 diffg".或输入"1,100 diffget".
#*先指定范围1-100行,再用指定3号缓冲(假设是文件file3)的不同处替换当前:
输入"1,100 diffg 3".或输入"1,100 diffget 3". #这里,在diffg后面指定缓冲名字
#等同于do不过指定了范围,如果有缓冲还可在diffg后面指定缓冲名字。
示例4.在vimdiff中上下文的展开和查看
比较和合并文件的时候经常需要结合上下文来确定最终要采取的操作,Vimdiff 缺省是会把不同之处上下各 6 行的文本都显示出来以供参考,其他的相同的文本行被自动折叠,如果希望修改缺省的上下文行数,可以这样设置:
:set diffopt=context:3 #就是不同之处的上3行和下3行不能折叠
#打开折叠代码。之所以用z这个字母,是因为它看上去比较像折叠着的纸:)
zo (folding open)
#重新折叠起来
zc (folding close)
描述:此命令主要应用于比较二进制文件,即逐字节比较两个文件。
语法参数
# 语法:
cmp [选项]... 文件1 [文件2 [跳1 [跳2]]]
<跳1> 和 <跳2> 分别是每个文件要略过的字节数。
# 参数:
-b --print-bytes 打印出内容相异的字节
-i, --ignore-initial=SKIP 两个输入内容都略过前 SKIP 字节
-i, --ignore-initial=跳1:跳2 略过 <文件1> 的前 <跳1> 个字节和文件 <文件2>
的前 <跳2> 个字节
-l, --verbose 输出所有相异字节的字节数和内容
-n, --bytes=限制 最多比较给定字节数的数据
-s, --quiet, --silent 禁止所有正常输出
--help 显示此帮助信息并退出
-v, --version 输出版本信息并退出
<跳> 值可以加上以下的单位:kB=1,000、K=1,024、MB=1,000,000、M=1,048,57
示例使用:
示例1.查看两个二进制文件是否相同,已dir命令与ls命令为例。
# 二进制示例文件
$ ls -lah /usr/bin/dir /usr/bin/ls
# -rwxr-xr-x. 1 root root 138K 4月 24 2023 /usr/bin/dir
# -rwxr-xr-x. 1 root root 138K 4月 24 2023 /usr/bin/ls
# 使用diff命令判断
$ diff /usr/bin/dir /usr/bin/ls
# 二进制文件 /usr/bin/dir 和 /usr/bin/ls 不同
# 使用cmd命令判断,更显示具体的不同的字节位置
$ cmp /usr/bin/dir /usr/bin/ls
# /usr/bin/dir /usr/bin/ls 不同:第 25 字节,第 1 行
# 使用hexdump命令查看文件偏移20Byte后的20个字节内容
$ hexdump -s 20 -Cn 20 /usr/bin/dir
00000014 01 00 00 00 f0(不同字节处) 6a 00 00 00 00 00 00 40 00 00 00 |.....j......@...|
00000024 00 00 00 00 |....|
00000028
$ hexdump -s 20 -Cn 20 /usr/bin/ls
00000014 01 00 00 00 10(不同字节处)6b 00 00 00 00 00 00 40 00 00 00 |.....k......@...|
00000024 00 00 00 00 |....|
00000028
描述:可以用于两个文件之间的比较( 逐行比较两个已排序的文件),它有一些选项可以用来调整输出,以便执行交集、求差、以及差集操作。如果<文件1>或<文件2>是"-"时(不含两者均为"-"的情况),将从标准输入读取。如果不附带选项,程序会生成三列输出。第一列包含文件1 特有的行,第二列包含 文件2 特有的行,而第三列包含两个文件共有的行。
知识扩展:
基础语法:
# 语法
comm [参数] 文件1 文件2 只打印在文件1 和文件2 中都有的行
# 参数
-1 不输出文件1 特有的行
-2 不输出文件2 特有的行
-3 不输出两个文件共有的行
--check-order 检查输入是否被正确排序,即使所有输入行均成对
--nocheck-order 不检查输入是否被正确排序
--output-delimiter=STR 依照STR 分列
--total 输出一份摘要信息
-z, --zero-terminated 以 NUL 字符而非换行符作为行尾分隔符
实际案例:
# 示例1.输出的第一列只包含在aaa.txt中出现的行,第二列包含在bbb.txt中出现的行,第三列包含在aaa.txt和bbb.txt中相同的行。各列是以制表符(\t)作为定界符。
$ comm aaa.txt bbb.txt
aaa
bbb
ccc
aaa
ddd
eee
111
222
hhh
ttt
jjj
第一列 第二列 第三列
# 示例2. 交集 打印两个文件的交集,需要删除第一列和第二列:
comm aaa.txt bbb.txt -1 -2 #即自显示第三列
# bbb
# ccc
# 或写作
comm -12 文件1 文件2 只打印在文件1 和文件2 中都有的行
# 示例3. 求差 打印出两个文件中不相同的行,需要删除第三列:
comm aaa.txt bbb.txt -3 | sed 's/^\t//'
# 连续的bbb,ccc可以匹配, 是将制表符(\t)删除,以便把两列合并成一列。
comm -3 t1.txt t2.txt --nocheck-order | tr -d '\t'
aaa
aaa
ddd
eee
111
222
hhh
ttt
jjj
comm -3 t1.txt t2.txt --nocheck-order | tr -d '\t' | uniq -u #删除重复的行
# 示例4.差集通过删除不需要的列,可以得到aaa.txt和bbb.txt的差集:
$comm aaa.txt bbb.txt -1 -3 #aaa.txt的差集
$comm aaa.txt bbb.txt -2 -3 #bbb.txt的差集
aaa
ddd
eee
111
222
若文章写得不错,不要吝惜手中转发,点赞、在看,若有疑问的小伙伴,可在评论区留言你想法哟💬!
温馨提示:作者最近10年的工作学习笔记(涉及网络、安全、运维、开发),需要学习实践笔记的看友,可添加作者账号[WeiyiGeeker],当前价格¥199,除了获得从业笔记的同时还可进行问题答疑以及每月远程技术支持,希望大家多多支持,收获定大于付出!
如果此篇文章对你有帮助,请你将它转发给更多的人!