head input > output 是否将所有不可见字符复制到新文件中?

Lás*_*zló 3 shell character-encoding text-processing head

我需要抓取长文本文件的第一行,以便在较小的文件上进行一些错误修复(Python 脚本没有按预期消化大文本文件)。然而,为了使错误修正有意义,我真的需要这些行是完美的副本,基本上是逐字节的,并找出字符编码、行尾字符、不可见字符或不可见字符的任何潜在问题原来的.txt 以下简单的解决方案会实现这一点,否则我会使用 的输出丢失一些东西head吗?

head infile.txt > output.txt
Run Code Online (Sandbox Code Playgroud)

在与二进制拷贝一个更一般的问题headdd或者别的现已公布在这里

Tho*_*key 10

POSIX 说输入head是一个文本文件,并定义了一个文本文件:

3.397 文本文件

包含组织成零个或多个行的字符的文件。这些行不包含 NUL 字符,并且任何行的{LINE_MAX}长度都不能超过字节,包括<newline>字符。尽管 POSIX.1-2008 不区分文本文件和二进制文件(参见 ISO C 标准),但许多实用程序仅在对文本文件进行操作时产生可预测或有意义的输出。具有此类限制的标准实用程序总是在其 STDIN 或 INPUT FILES 部分中指定“文本文件”。

因此存在丢失信息的可能性。


ter*_*don 5

显然,head当它不是文本文件时,它的输入确实会出现乱码:

$ wc /bin/ls
   431   3454 126496 /bin/ls
$ head -n 431 /bin/ls > a
 wc a
   431   3447 125378 a
$ diff a /bin/ls
Binary files a and /bin/ls differ
$ md5sum /bin/ls a
42846aa64774a99f0f1feba36ec2e099  /bin/ls
de032f5aa5ef356fb7d5ab4dc622df2e  a
$ wc -c /bin/ls a
126496 /bin/ls
125378 a
Run Code Online (Sandbox Code Playgroud)

Stéphane Chazelas 在评论中提出了一个很好的观点:

wc -l报告换行数。/bin/ls可能在最后一次出现后有更多字节0xahead -n 431不会输出。GNU 工具(您似乎正在使用)通常可以处理二进制数据(NUL 字节和任意长的行)。

所以,使用时输出错误的原因是head -n最后一个\n字符后有多余的数据。查看 GNU 的源代码head,我可以确认按行读取的函数和按字节读取的函数使用相同的safe_open()调用,因此它们能够返回的内容之间确实不应该有任何区别。这表明使用 GNU 实现head(通常在大多数使用 Linux 的非嵌入式操作系统中发现)是非常安全的。

但是,如果您告诉它处理字节而不是行(来自man head),它看起来可以正常工作:

  -c, --bytes=[-]NUM
          print  the  first  NUM bytes of each file; with the leading '-',
          print all but the last NUM bytes of each file
Run Code Online (Sandbox Code Playgroud)

使用该-c选项,它似乎创建了相同的文件:

$ wc -c /bin/ls
126496 /bin/ls
$ head -c 126496 /bin/ls > a
$
$ md5sum /bin/ls a
42846aa64774a99f0f1feba36ec2e099  /bin/ls
42846aa64774a99f0f1feba36ec2e099  a
Run Code Online (Sandbox Code Playgroud)

这也与通过dd以下获得的结果相同:

$ dd if=/bin/ls of=a bs=126496 count=1
1+0 records in
1+0 records out
126496 bytes (126 kB, 124 KiB) copied, 0.000469919 s, 269 MB/s
$ diff a /bin/ls
$
Run Code Online (Sandbox Code Playgroud)

我无法指出任何官方文档指定使用该-c标志时,它将始终产生正确的二进制输出,但这似乎是一个合理的假设。

  • `wc -l` 报告换行符的数量。`/bin/ls` 可能在最后一次出现 0xa 之后有更多字节,`head -n 431` 不会输出。GNU 工具(您似乎正在使用)通常可以处理二进制数据(NUL 字节和任意长的行)。 (2认同)