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

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

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

head infile.txt > output.txt

现在发布了关于带有head, , or else的二进制副本的更一般性问题dd这里

答案1

POSIX 表示输入head是一个文本文件, 和定义一个文本文件:

3.397 文本文件

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

所以存在丢失信息的可能性。

答案2

显然,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

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

wc -l报告换行数。/bin/ls在最后一次出现 后可能有更多字节0xa,这head -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

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

$ wc -c /bin/ls
126496 /bin/ls
$ head -c 126496 /bin/ls > a
$
$ md5sum /bin/ls a
42846aa64774a99f0f1feba36ec2e099  /bin/ls
42846aa64774a99f0f1feba36ec2e099  a

这也与通过以下方式获得的结果相同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
$

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

答案3

您可以使用split(1)。这将创建许多文件,每个文件对应于文件的字节正确的切片。

示例:FILE=test ; split -b 1000 $FILE $FILE.split.将创建 1000 字节的文件 test.split.aa 和 test.split.ab 等,cat $FILE.split.* > $FILE.recompose并将生成与原始 $FILE 相同的 $FILE.recompose。如果您的文件大于 1000*26*26 那么您需要增加后缀长度(请参阅man split

有了split -l 100它,每个文件将放置 100 行。我相当有信心这将是字节正确的。

相关内容