有点不寻常的用例:我从 Firefox 下载了一个文件,它实际上是一个数据流。我想(近)实时处理它,而不保存数据(数据量很大,会很快填满我的驱动器)。有没有一种方法可以将正在下载的文件转换为某种管道/套接字,然后以某种方式直接以编程方式读取它?
到目前为止我尝试过的事情:
让脚本定期将文件移动到不同的位置,将移动的文件读入缓冲区,然后重复读取流。不幸的是,这样做会停止下载(Firefox 继续下载,但移动原始文件后没有出现新的 .part 文件)。
我发现如果我只是写入文件(echo '' > file.part),下载就会继续。所以我可以读取内容,覆盖文件(以避免填满空间),然后无限地重复 - 但是在读取文件和覆盖文件之间,Firefox 同时会写入更多字节,因此流会被损坏。
有想法吗?
根据评论中的问题提供一些详细信息:
下载是一个捕获 (pcap) 文件,其下载由 Fritzbox Web UI 启动。我无法卷曲它,因为它是 fritzbox 以某种方式启动下载,没有我可以在卷曲中使用的 url。不确定下载是如何实现的,因为它在 Firefox 中显示为“正常”下载,但没有设置大小,并且它会不断添加数据,直到我在网络用户界面中按“停止”为止。
答案1
如果您的文件系统支持fallocate()
系统调用,例如ext4
,那么您可以使用它将已读取的文件部分清零,并且它们使用的空间也将变为零,因为文件将变为疏。
例如:
file=/tmp/somefile
length=4096
offset=0
tail -n +1 -f "$file" |
while timeout 5 dd status=none count=1 bs=$length
do fallocate --punch-hole -o $offset -l $length $file
let offset=offset+length
done |
myprogram
该 shell 脚本用于tail
从块 0 读取文件,通过管道将数据dd
读取单个块并将其通过管道传输到您的程序。然后它使用该实用程序fallocate
将该块清零。
将ls -ls $file
显示由 Firefox 写入的文件的大小不断增长,但第一个数字(使用的块数)将接近于零(假设循环设法跟上)。如果需要,增加长度,将其保持为文件系统块大小的倍数。用于timeout
检测最终的文件结束符,并且可能需要扩展。