有没有简单的方法可以截断管道中的文件?具体来说,我想在将文件送入另一个进程之前截断文件的最后四个字节。
理想情况下,我可以写类似这样的内容:
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)