Linux 中的 Cat 命令:基本和高级示例Linux 中的 Cat 命令:基本和高级示例Linux 中的 Cat 命令:基本和高级示例Linux 中的 Cat 命令:基本和高级示例
  • 文章
  • 正则表达式
    • 工具
  • 登录
找到的结果: {phrase} (显示: {results_count} 共: {results_count_total})
显示: {results_count} 共: {results_count_total}

加载更多搜索结果...

搜索范围
模糊匹配
搜索标题
搜索内容
发表 admin at 2025年2月28日
类别
  • 未分类
标签

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

cat 是 Linux 中最常用的命令之一,但你真的了解 cat 命令吗?了解 Linux 中 cat 命令的基础知识和高级示例。

继续上周从 ls 命令开始的那些不太为人所知的命令的浏览,今天让我们检查一下 cat 命令。

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 和 GNU cat 实现移植。请注意,我在这里并不假装详尽无遗,因此请检查 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
sylvain@bulbizarre:~$ 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选项编号,因为它们是空的。但是第 6 行呢?为什么仍然使用 -b 选项进行编号?嗯,因为它是一个空白行,但不是一个空行,我们将在下一篇中看到部分。

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

三个选项 -v、-e ` 和 `-t 用于显示不同的不可见字符集。即使这些集合重叠,也没有“包罗万象”的选项,因此如果您想显示所有不可见字符,则必须将它们组合起来。

-v:查看不可见字符

-v 选项显示所有带有插入符号和元表示法的非打印字符,除了换行符和制表符。

使用该选项,控制字符将显示为脱字号 (^),后跟相应的 ASCII 字符(例如,回车符、字节 13 显示为 ^M,因为ASCII 中的 M 为 64 + 13),设置高位的字符将以“meta”表示法 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^@^@^B@^@^@
^@^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标记了吗?它们用于替换其他不可见的回车符。它从哪里来的?与任何其他 Internet 协议一样,dict 协议使用 CRLF 作为行终止符。因此我们将它们作为示例文件的一部分下载。您可以在 fold 和 fmt 文章中了解有关换行和回车的更多信息。但现在,它解释了为什么 cat 认为第 6 行不为空。

-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 和 -选项:

$ 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$
$

奖励:Linux 中 cat 命令的无用使用

如果没有提到“无用地使用 Cat”反模式,任何有关 cat 命令的文章都是不完整的。

当您使用 cat 的唯一目的是将文件内容发送到另一个命令的标准输入时,就会发生这种情况。使用 cat 命令被认为是“无用的”,因为简单的重定向或文件名参数就可以完成这项工作,而且会做得更好。但一个值得一千字的例子:

$ curl -so - dict://dict.org/'d:uuoc:jargon' |    sed -Ee '/^151/,/^[.]/!d;/^[.0-9]/s/.*//'  > uuoc.txt
$ cat uuoc.txt | less

UUOC


    [from the comp.unix.shell group on Usenet] Stands for Useless Use of {cat};
    the reference is to the Unix command cat(1), not the feline animal. As
    received wisdom on comp.unix.shell observes, ?The purpose of cat is to
    concatenate (or ?catenate?) files. If it's only one file, concatenating it
    with nothing at all is a waste of time, and costs you a process.?
    Nevertheless one sees people doing


    cat file | some_command and its args ...

    instead of the equivalent and cheaper


    <file some_command and its args ...

    or (equivalently and more classically)


    some_command and its args ... <file
[...]

在上面的示例中,我使用管道通过 less 分页器显示 uuoc.txt 文件的内容:

cat uuoc.txt | less

因此,cat 命令的唯一目的是向 less 命令的标准输入提供 uuoc.txt 文件的内容。我会使用 shell 重定向获得相同的行为:

less < uuoc.txt

事实上,less 命令与许多命令一样,也接受文件名作为参数。所以我可以简单地写成:

less uuoc.txt

正如您所看到的,这里不需要 cat 。如果我提到“猫的无用使用”反模式,这是因为,如果您在论坛或其他地方公开使用它,毫无疑问有人会指出您将创建一个“无用的额外过程”。 ”

我必须承认,很长一段时间我对这样的评论很不屑一顾。毕竟,在我们的现代硬件上,为一次性操作生成一个额外的进程不会导致那么多开销。

但在撰写本文时,我做了一个快速实验,通过测试 awk 脚本比较了使用和不使用 UUOC 时处理来自慢速介质的 500MB 数据所需的时间。

令我惊讶的是,差异绝非可以忽略不计:

然而,原因并不是创建了额外的进程。但由于 UUOC 需要额外的读/写和上下文切换(您可以从执行系统代码所花费的时间推断出这一点)。因此,事实上,当您处理大型数据集时,额外的 cat 命令会产生不可忽略的成本。至于我自己,我现在会尽量提高警惕!你呢?如果您有 Cat 无用用途的例子,请随时与我们分享!

©2015-2025 艾丽卡 support@alaica.com