批处理:GNU-make、Snakemake 还是什么?

Batch processing: GNU-make, Snakemake or what?

我需要通过将目录中的一组文件传递给 matlab 或 python 脚本来处理它们。

对于目录中的每个输入文件FileName.IN,我需要获得一个输出文件FileName.OUT。

解决方案是 Python 还是 bash 脚本并不重要。

为了实现我的目标,我尝试了 GNU Make(或 Python Snakemake),但是我有点卡在上面。 看起来我可以说 GNU Make 要做: " 嘿,对于每个输出(目标)文件 FileName.out 搜索相应的 FileName.IN(先决条件)"

然而我想做的恰恰相反,如前所述。

我的 makefile 代码看起来像这样,但它不能完成工作(我是 GNU make 的新手):

in_files = *.IN
out_files = *.out
$(out_files) : $(in_files)
    matlab -nosplash -nodesktop -r "a_matlab_function('$<','$@')"

我想你只是想要一个 bash for 循环:

for f in *.IN; do
   out=${f%IN}OUT                # Work out name of output file
   echo IN:"$f"                  # Show input file to user
   echo OUT:"$out"               # Show output file to user
   matlab <options> "$f" "$out"  # Run Matlab
done

所以,如果我有这些文件:

ls *IN

aThird.IN   
another one.IN
b.IN

我会得到这个:

IN:aThird.IN
OUT:aThird.OUT
IN:another one.IN
OUT:another one.OUT
IN:b.IN
OUT:b.OUT

或者,作为 one-liner:

for f in *.IN; do out=${f%IN}OUT; matlab ... "$f" ... "$out"; done

备注:

虽然你的问题建议使用 make,但没有明确的迹象表明你是否总是期望 运行 所有作业,或者是否有时某些作业不需要 运行ning - 大概是因为输出文件已经存在,没有必要 运行 它们。如果你不想要所有的工作 运行 每次,你可能会更好 make.

此外,如果 Matlab 可以 运行 并行实例,GNU Parallel 语法非常适合这样的事情:

parallel --dry-run matlab {} {.}.OUT ::: *IN

输出

matlab another\ one.IN another\ one.OUT
matlab aThird.IN aThird.OUT
matlab b.IN b.OUT 

在这里,--dry-run 向您展示了 运行 的命令,尽管它目前没有 运行 任何东西。

我对 Snakemake 一无所知,但在 GNU Make 中你可以转换 in_files 以提供 out_files:

in_files = $(wildcard *.IN)
out_files = $(in_files:.IN=.out)

然后你制作一个依赖于所有输出的虚拟目标:

all: $(out_files)
.PHONY: all

最后是从一个输入创建一个输出的规则:

%.out: %.IN
    matlab -nosplash -nodesktop -r "a_matlab_function('$<','$@')"