在管道中截断文件

在管道中截断文件

有没有简单的方法可以截断管道中的文件?具体来说,我想在将文件送入另一个进程之前截断文件的最后四个字节。

理想情况下,我可以写类似这样的内容:

cat input.txt | some-process | truncate --size=-4 | another-process > output.txt

但看起来该truncate命令仅对磁盘上的文件“就地”进行操作。

答案1

这就像我告诉你,当我说出倒数第四个字我就要说了。我不会提前告诉你们我要说多少话。

管道是溪流。其数据没有大小,只有从中获取下一个元素和/或向其中插入一个元素的操作,结果要么是一段数据,要么是没有更多数据的信号。

因此,除非您首先从流中检索所有数据,将其放入缓冲区,计算其长度,“倒回”流,然后检索少四个元素,否则无法完成。

编辑:我需要多思考,而不是想出巧妙的类比:)流不会说“在最后一个元素前立即停止”,而是“传输除最后 n 个元素之外的所有元素”,通过维护仅 n 个元素的缓冲区,并等待前 n 个元素被接收后再传输第一个元素,这是可能的。显然,这在电信等情况下行不通,因为您希望在收到数据后立即发送数据,而如果您想要前 n 个元素,则可以这样做。我认为truncate不是这样做的。

(尝试降低自己投票 -1)

答案2

写完那个 Python 脚本后我感觉自己很傻。

有一个内置的 shell 命令head可以执行此操作:

cat input.txt | some-process | head --bytes=-4 | another-process > output.txt

编辑:GNUhead命令有一个概念上类似的实现(即节省内存)我的 Python 实现N下面。一个区别是它将循环缓冲区的大小( ,省略的字节数)四舍五入为某个标准缓冲区大小的倍数。

答案3

sed可以对最后一行进行操作。假设最后 4 个字符位于一行上:

printf "%s\n" abcdef ghijkl mnopqr | sed '$s/....$//'

输出

abcdef
ghijkl
mn

答案4

上午也花了一部分时间编写 Python 脚本。当然,你最好用“头脑”而不是编写更多代码。无论如何,这是我的版本。它很丑陋,但我认为这是我有史以来的第一个 Python 脚本:

#!/usr/bin/python

# stream_trunc: cut the last n bits of a stream

import sys

if len(sys.argv) <> 2:
    print 'Usage: ' + sys.argv[0] + ' <number>'
    exit(1)

num = sys.argv[1]

if num.isdigit() != True:
    print 'Argument should be a number'
    print 'Usage: ' + sys.argv[0] + ' <number>'
    exit(1)

n = int(num)
buf = sys.stdin.read(n)
c = sys.stdin.read(1)

while c != '':
    sys.stdout.write(buf[0])
    buf = buf[1:] + c
    c = sys.stdin.read(1)

相关内容