我想执行以下命令:
dune exec -- ocaml-print-intf file.ml
并将其输出重定向到file.mli
问题是我不会写
dune exec -- ocaml-print-intf file.ml > file.mli
因为file.mli
创建然后dune exec -- ocaml-print-intf file.ml
执行并且其输出被重定向到file.mli
.为什么这是一个问题?因为它应该生成签名,file.ml
但它检查的第一件事是是否已经存在签名文件(file.mli
在我们的例子中),如果存在则输出它。
例子:
❯ dune exec -- ocaml-print-intf src/file.ml
val a : int
val b : string
❯ dune exec -- ocaml-print-intf src/file.ml > src/file.mli
❯ cat src/file.mli
❯ dune exec -- ocaml-print-intf src/file.ml
我找到了一个解决方案海绵
❯ dune exec -- ocaml-print-intf src/file.ml | sponge src/file.mli
❯ cat src/file.mli
val a : int
val b : string
但我想知道是否有另一种解决方案不需要安装外部软件。
答案1
使用ksh93
,您可以执行以下操作:
dune exec -- ocaml-print-intf src/file.ml >; src/file.mli
>;word
将输出写入临时文件。如果命令成功完成,请将其重命名为 word,否则,删除临时文件。>;word
不能与内置的 exec 一起使用。
您还可以sponge
用一行perl
代码进行模拟:
dune exec -- ocaml-print-intf src/file.ml |
perl -0777 -spe 'open STDOUT, ">", $out or die "$out: $!\n"' -- -out=src/file.mli
一旦在输入中找到 eof ,就将sponge
整个输入存储在内存中,然后将其转储到输出文件中。
在 中zsh
,你可以这样做:
mv =(dune exec -- ocaml-print-intf src/file.ml) src/file.mli
其中=(cmd)
扩展为包含 的输出的临时文件的路径cmd
。请注意文件的权限将受到限制。
答案2
您注意到它适用于sponge
:
dune exec -- ocaml-print-intf src/file.ml | sponge src/file.mli
这是因为在收集完所有数据后才sponge
创建名称。src/file.mli
sponge
您可以通过简单地重定向到不同名称的文件,然后在收集数据后将其移动到正确的名称来完成此操作:
dune exec -- ocaml-print-intf src/file.ml >tmpfile &&
mv tmpfile src/file.mli
这假设tmpfile
可以用作中间文件。如果dune
失败,那么就必须清理中间文件。考虑到这一点,以下内容:
if dune exec -- ocaml-print-intf src/file.ml >tmpfile
then
mv tmpfile src/file.mli
else
rm tmpfile
fi
使用mktemp
创建临时文件:
tmpfile=$(mktemp)
if dune exec -- ocaml-print-intf src/file.ml >"$tmpfile"
then
mv "$tmpfile" src/file.mli
else
rm "$tmpfile"
fi