我有一个大小为 2GB 的文件,想要分块读取并将每块传递给命名管道。
例如;
mkfifo /tmp/pipe
tail -c 200 myfile > /tmp/pipe & #last 200 bytes of file in the pipe.
use the /tmp/pipe.
我想将一些固定已知大小的数据传递到命名管道,然后将该管道传递到 lftp。现在,一旦完成此操作,再次在管道中加载下一个字节并执行 lftp 操作。
如何从文件中读取 5MB(或任何大小,比如 x),然后将其传递给管道,然后使用该管道,然后继续到下一个 5MB 并继续,直到到达文件末尾。
答案1
一个简单的解决方案是使用split --filter=…
。
--filter=COMMAND
写入 shellCOMMAND
;文件名为$FILE
(来源)
该--filter
选项不可移植,希望您split
支持它。GNU split
coreutils 支持。该选项接受 shell 命令。我对 GNU 的测试表明该工具使用在(或如果未设置)split
中指定的 shell 。$SHELL
sh
shell 命令可能非常复杂。或者,您可以调用任意复杂的脚本 ( --filter=/path/to/script.sh
)。该命令或脚本将为每个片段调用一次,片段将通过其 stdin 进入。如果您可以从 stdin 读取,则不需要额外的(命名)管道。
如果你的操作系统提供了/dev/stdin
,那么我相信在你的情况下 shell 命令可能是:
lftp … -e "put /dev/stdin -o $FILE"
您应该将其中的内容替换…
为服务器地址,以及满足您需求的其他内容。我承认我只是粗略地测试了该命令,它来自这个答案。
你的split
命令将如下所示:
split -b 5242880 --filter='
lftp … -e "put /dev/stdin -o prefix-$FILE"
' myfile
注意$FILE
不能由本地 shell 扩展,它应该是单引号(并且它是,请参阅这个问题)。将使用环境中split
的正确相应值运行内壳。内壳的上下文中不能使用单引号。$FILE
$FILE
该命令将在服务器上创建名称以 开头的文件prefix-
。除非当地语言环境很奇怪,否则名称将按应有的方式排序,因此此命令:
cat prefix-* > myfile
在服务器上的 shell 中调用(在本地split
成功发送所有片段后)将在那里创建原始文件的副本。如果您怀疑语言环境很奇怪(或者您只是想保险起见),请使用:
(LC_COLLATE=C; cat prefix-* > myfile)