是否可以在创建要在其中重定向其输出的文件之前执行命令

是否可以在创建要在其中重定向其输出的文件之前执行命令

我想执行以下命令:

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

相关内容