Linux中的Cat命令:基本示例和高级示例

时间:2020-03-05 15:26:03  来源:igfitidea点击:

“ cat”名称代表“ catenate”,因为该命令的主要工作是通过按顺序在标准输出上发送其内容来联接多个输入文件:

# Let's obtain first some sample data files:
curl -so - dict://dict.org/'d:felidae:gcide' | unexpand -a -t 3 |
  sed -Ee '/^151/,/^[.]/!d;/^[.0-9]/s/.*//' > felidae.txt
curl -so - dict://dict.org/'d:felis:gcide' | unexpand -a -t 3 |
  sed -Ee '/^151/,/^[.]/!d;/^[.0-9]/s/.*//' > felis.txt
# Catenate files
cat felidae.txt felis.txt

如果要将连接结果存储在文件中,则必须使用shell重定向:

cat felidae.txt felis.txt > result.txt
cat result.txt

即使其主要设计目标是对文件进行分类,也经常使用cat实用程序仅使用一个参数将该文件的内容显示在屏幕上,就像我在上面示例的最后一行所做的一样。

A.在标准输入中使用cat命令

当不带任何参数使用时,cat命令将从其标准输入读取数据并将其写入其标准输出-这几乎是无用的……除非我们使用某些选项来转换数据。
稍后我们将讨论几个有趣的选项。

除了文件路径,cat命令还可以将-特殊文件名理解为标准输入的别名。
这样,我们可以将从标准输入中读取的数据插入命令行中给出的文件之间:

# Insert a separator between the two concatenated files
echo '----' | cat felis.txt - felidae.txt

B.对二进制文件使用cat命令

1.连接分割文件

cat命令不会对文件内容做任何假设,因此可以愉快地使用二进制数据。

重新加入由split或者csplit命令破坏的文件时可能有用的东西。

或者加入部分下载,就像我们现在要做的那样:

## A picture by Von.grzanka (CC-SA 3.0)
# Optimize bandwidth usage by breaking the download in two parts
# (on my system, I observe a 10% gain that way compared to a "full" download)
curl -s -r 0-50000 \
    https://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/Felis_catus-cat_on_snow.jpg/1024px-Felis_catus-cat_on_snow.jpg \
    -o first-half &
curl -s -r 50001- \
    https://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/Felis_catus-cat_on_snow.jpg/1024px-Felis_catus-cat_on_snow.jpg \
    -o second-half &
wait

现在,我们将图像分为两半。
我们可以使用ImageMagick的display或者gimp或者任何其他能够读取图像文件的软件打开前半部分,并查看其是否已损坏:

display first-half
# -or
gimp first-half
# -or
firefox first-half

如果研究我使用的curl命令,我们会发现这两个部分是完全互补的。
前半部分从字节0到50000,后半部分从字节50001到文件末尾。
它们之间应该没有丢失的数据。
因此,我们只需要将两个部分连接在一起(以正确的顺序)即可获取完整文件:

cat first-half second-half > image.jpg
display image.jpg

2.使用流式文件格式

我们不仅可以使用“ cat”命令来“重新加入”被分成几部分的二进制文件,而且在某些情况下,还可以以这种方式创建新文件。
这对于“无头”或者“可流式”文件格式(例如MPEG传输流视频文件(“ .TS”文件))特别有效:

# Let's make a still video file from our picture
ffmpeg -y -loop 1 -i cat.jpg -t 3  \
    -c:v libx264 -vf scale=w=800:h=-1 \
    still.ts
# Let's make a fade-in from the same picture
ffmpeg -y -loop 1 -i cat.jpg -t 3  \
    -c:v libx264 -vf scale=w=800:h=-1,fade=in:0:75 \
    fadein.ts
# Let's make a fade-out from the same picture
ffmpeg -y -loop 1 -i cat.jpg -t 3  \
    -c:v libx264 -vf scale=w=800:h=-1,fade=out:0:75 \
    fadeout.ts

现在,我们可以使用cat命令合并所有这些传输流视频文件,从而在输出中获得完全有效的TS文件:

cat fadein.ts still.ts fadeout.ts > video.ts
mplayer video.ts

借助TS文件格式,我们可以按所需顺序组合这些文件,甚至可以在参数列表中多次使用同一文件,以在输出视频中创建循环或者重复。
显然,如果我们使用动画图像,这会更有趣,但是我可以让你自己做:许多消费级设备都记录TS文件,如果没有,我们仍然可以使用ffmpeg来转换任何视频文件到传输流文件。
请不要在注释列里分享作品!

3.破解cpio档案

作为最后一个示例,让我们看看如何使用“ cat”命令来组合多个“ cpio”归档文件。

但是这次,它并不会那么简单,因为它将需要一些有关cpio存档文件格式的知识。

cpio归档文件按顺序存储文件的元数据和内容,这使其适用于通过cat实用程序进行文件级串联。
不幸的是,cpio归档文件还包含一个预告片,用于标记归档文件的结尾:

# Create two genuine CPIO `bin` archive:
$find felis.txt felidae.txt | cpio -o > part1.cpio
2 blocks
$echo cat.jpg | cpio -o > part2.cpio
238 blocks
$hexdump -C part1.cpio | tail -7
000002d0  2e 0d 0a 09 09 20 20 5b  57 6f 72 64 4e 65 74 20  |.....  [WordNet |
000002e0  31 2e 35 5d 0d 0a 0a 00  c7 71 00 00 00 00 00 00  |1.5].....q......|
000002f0  00 00 00 00 01 00 00 00  00 00 00 00 0b 00 00 00  |................|
00000300  00 00 54 52 41 49 4c 45  52 21 21 21 00 00 00 00  |..TRAILER!!!....|
00000310  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000400
$hexdump -C part2.cpio | tail -7
0001da40  46 96 ab f8 ad 11 23 90  32 79 ac 1f 8f ff d9 00  |F.....#.2y......|
0001da50  c7 71 00 00 00 00 00 00  00 00 00 00 01 00 00 00  |.q..............|
0001da60  00 00 00 00 0b 00 00 00  00 00 54 52 41 49 4c 45  |..........TRAILE|
0001da70  52 21 21 21 00 00 00 00  00 00 00 00 00 00 00 00  |R!!!............|
0001da80  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
0001dc00

好的新功能是,使用cpio二进制归档文件,该预告片的固定长度为280个字节。
因此,使用head标准命令,我们有一种简单的方法可以将其删除:

# Each archive end with the 280-byte trailer.
# To catenate both archives, just remove the trailer
# at the end of the first part:
$head -c-280 part1.cpio | cat - part2.cpio > cat.cpio
$cpio -it < cat.cpio
felis.txt
felidae.txt
cat.jpg
239 blocks

C.基本的cat命令选项

在使用了各种二进制文件格式后,让我们现在通过研究几个专门为处理这些文件而设计的选项,回到普通的旧文本文件。
这些选项虽然不是POSIX标准的一部分,但可以跨BSD和GNUcat实现移植。
请注意,我在这里并不假装详尽无遗,因此请检查man以查看系统上cat支持的选项的完整列表!

-n:数字行

使用n选项,cat命令将在每条输出行的行号前添加前缀:

cat -n felidae.txt
     1
     2    Felidae \Felidae\ n.
     3       a natural family of lithe-bodied round-headed fissiped
     4       mammals, including the cats; wildcats; lions; leopards;
     5       cheetahs; and saber-toothed tigers.
     6
     7       Syn: family {Felidae}.
     8            [WordNet 1.5]
     9

-n选项为输出行编号。
这意味着从一个输入文件切换到下一个输入文件时不会重置计数器,因为如果我们自己尝试以下命令,我们将看到它:

cat -n feli*.txt

-s:抑制重复的空输出行

使用-s选项,cat命令将只折叠多个连续的空行:

cat -n felis.txt felidae.txt | sed -n 8,13p
     8       lynx ({Felis lynx}) is also called {Lynx lynx}.
     9       [1913 Webster +PJC]
    10
    11
    12    Felidae \Felidae\ n.
    13       a natural family of lithe-bodied round-headed fissiped
Hyman@theitroad:~$cat -ns felis.txt felidae.txt | sed -n 8,13p
     8       lynx ({Felis lynx}) is also called {Lynx lynx}.
     9       [1913 Webster +PJC]
    10
    11    Felidae \Felidae\ n.
    12       a natural family of lithe-bodied round-headed fissiped
    13       mammals, including the cats; wildcats; lions; leopards;

在上面的示例中,我们可以在默认输出中看到第10行和第11行为空。
当添加-s选项时,第二个空行被丢弃。

-b:仅对非空行编号

与前两个选项有些相关,-b选项将对行进行编号,但忽略空行:

$cat -b felidae.txt | cat -n
     1
     2         1    Felidae \Felidae\ n.
     3         2        a natural family of lithe-bodied round-headed fissiped
     4         3        mammals, including the cats; wildcats; lions; leopards;
     5         4        cheetahs; and saber-toothed tigers.
     6         5
     7         6        Syn: family {Felidae}.
     8         7              [WordNet 1.5]
     9

上面的示例在管道中使用了带有不同选项的cat命令的两个实例。
内部编号来自与第一个cat命令一起使用的-b选项。
外部编号来自与第二个cat一起使用的-n选项。

如我们所见,第一行和最后一行没有用-b选项编号,因为它们为空。
但是第六行呢?
为什么仍然用-b选项编号?
好吧,因为这是一个空行,但不是空行,我们将在下一部分中看到。

-v-e-t:显示非打印字符

三个选项-v,-e和-t用于显示不同的不可见字符集。
即使集合重叠,也没有“ catch-all”选项,因此,如果要显示所有不可见的字符,则必须将它们合并。

-v:查看不可见的字符

-v选项以换行符和制表符显示所有带有脱字符号和元标记的非打印字符。

使用该选项,控制字符将显示为插入记号(^),后跟适当的ASCII字符(例如,回车符,字节13,显示为^ M,因为ASCII中的“ M”为64 + 13)。
,并且设置了高位的字符将以“元”表示法“ M-”出现,后跟与7个低位相对应的表示(例如,字节141将显示为“ M- ^ M”,因为141为128 + 13)。

尽管看起来有些深奥,但该功能在处理二进制文件时可能很有用,例如,如果我们要检查JPEG文件中嵌入的原始信息,则:

$cat -v cat.jpg | fold -75 | head -10
M-^?M-XM-^?M-`^@^PJFIF^@^A^A^A^@H^@H^@^@M-^?M-~^@QFile source: http://commo
ns.wikimedia.org/wiki/File:Felis_catus-cat_on_snow.jpgM-^?M-b^LXICC_PROFILE
^@^A^A^@^@^LHLino^B^P^@^@mntrRGB XYZ ^GM-N^@^B^@    ^@^F^@1^@^@acspMSFT
^@^@^@^@IEC sRGB^@^@^@^@^@^@^@^@^@^@^@^@^@^@M-vM-V^@^A^@^@^@^@M-S-HP  ^@^@^
@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@
^@^@^@^@^@^@^@^Qcprt^@^@^AP^@^@^@3desc^@^@^AM-^D^@^@^@lwtpt^@^@^AM-p^@^@^@^
Tbkpt^@^@^B^D^@^@^@^TrXYZ^@^@^B^X^@^@^@^TgXYZ^@^@^B,^@^@^@^TbXYZ^@^@^Hyman@theitroad^@^@
^@^Tdmnd^@^@^BT^@^@^@pdmdd^@^@^BM-D^@^@^@M-^Hvued^@^@^CL^@^@^@M-^Fview^@^@^
CM-T^@^@^@$lumi^@^@^CM-x^@^@^@^Tmeas^@^@^D^L^@^@^@$tech^@^@^D0^@^@^@^LrTRC^
@^@^D<^@^@^H^LgTRC^@^@^D<^@^@^H^LbTRC^@^@^D<^@^@^H^Ltext^@^@^@^@Copyright (

-v选项的另一个用例是查找可能泄漏到文本文件中的控制字符。
如果我们还记得的话,上面有一个奇怪的问题,即-b选项在第6输入行编号,而看上去好像是空的。
因此,让我们调查一下:

$cat -v felidae.txt
Felidae \Felidae\ n.^M
    a natural family of lithe-bodied round-headed fissiped^M
    mammals, including the cats; wildcats; lions; leopards;^M
    cheetahs; and saber-toothed tigers.^M
^M
    Syn: family {Felidae}.^M
          [WordNet 1.5]^M

啊啊!我们看到那些“ ^ M”标记了吗?
它们用于替换原本不可见的回车符。
它从其中来的?
嗯,“ dict”协议与其他任何Internet协议一样,都使用CRLF作为线路终止符。

因此,我们将它们下载为示例文件的一部分。
我们可以在“ fold”和“ fmt”文章中了解有关换行符和回车符的更多信息。

但是现在,它解释了为什么“cat ”认为第六行不为空。

-e:显示不可见的字符,包括行尾

-e选项的作用类似于-v选项,除了它还会在每个换行符之前添加一个美元符号($),从而明确显示行尾:

$cat -e felidae.txt
$
Felidae \Felidae\ n.^M$
    a natural family of lithe-bodied round-headed fissiped^M$
    mammals, including the cats; wildcats; lions; leopards;^M$
    cheetahs; and saber-toothed tigers.^M$
^M$
    Syn: family {Felidae}.^M$
          [WordNet 1.5]^M$
$

-t:显示不可见的字符,包括制表符

-t选项的作用类似于-v选项,除了它还会显示使用^ I脱字号表示的制表符(制表符存储为字节的值9,ASCII中的I表示64+ 9 = 73):

$cat -t felidae.txt
Felidae \Felidae\ n.^M
^Ia natural family of lithe-bodied round-headed fissiped^M
^Imammals, including the cats; wildcats; lions; leopards;^M
^Icheetahs; and saber-toothed tigers.^M
^M
^ISyn: family {Felidae}.^M
^I^I  [WordNet 1.5]^M

-et:显示所有隐藏的字符

如前所述,如果要显示所有非打印字符,包括列表和行尾标记,则需要同时使用-e和-t选项:

$cat -et felidae.txt
$
Felidae \Felidae\ n.^M$
^Ia natural family of lithe-bodied round-headed fissiped^M$
^Imammals, including the cats; wildcats; lions; leopards;^M$
^Icheetahs; and saber-toothed tigers.^M$
^M$
^ISyn: family {Felidae}.^M$
^I^I  [WordNet 1.5]^M$
$