批处理: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(先决条件)"。
然而我想做的恰恰相反,如前所述。
make
(或snakemake
)是正确的选择吗?
- 您还有什么建议?
我的 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('$<','$@')"
我需要通过将目录中的一组文件传递给 matlab 或 python 脚本来处理它们。
对于目录中的每个输入文件FileName.IN,我需要获得一个输出文件FileName.OUT。
解决方案是 Python 还是 bash 脚本并不重要。
为了实现我的目标,我尝试了 GNU Make(或 Python Snakemake),但是我有点卡在上面。 看起来我可以说 GNU Make 要做: " 嘿,对于每个输出(目标)文件 FileName.out 搜索相应的 FileName.IN(先决条件)"。
然而我想做的恰恰相反,如前所述。
make
(或snakemake
)是正确的选择吗?- 您还有什么建议?
我的 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('$<','$@')"