循环覆盖文件



我需要在一个目录中的数千个文件上运行一个命令。但是,我使用的程序需要一个参数文件,在该文件上可以指示输入和输出的名称。命令如下:

./program parameters_file.txt

这些是我需要在parameters_file.txt上编辑的行,即第1-3行。其余行(未显示(保持不变:

input_file = asd123.OK 
input_file2 = asd123.TXT    
outfile = asd123.RESULTS_OUT          

如图所示,所有文件都有匹配的名称,并且只有扩展名发生了更改。

我需要循环这个,以便每次循环重新启动时都覆盖input_file、input_file2和outfile。类似于:用第一个文件名编辑parameters_file.txt,在第一个文件上运行命令,用第二个文件名修改parameters_file.txt,在第二个档案上运行命令等。

思考:

for f in *.OK;
do
input_file = $f 
input_file2 = $f.TXT    
outfile = $f.RESULTS_OUT 

但我不知道如何将其包含在命令中,也无法在parameters_file.txt中写入循环,因为这会使程序崩溃。可能是回显parameters_file.txt还是用sed覆盖?

谢谢。

如果你有数千个文件要处理,每个文件需要一个小时,你可以考虑使用GNU并行并行完成4、8或16个文件,并让所有的CPU核心都很忙,为此你花了英特尔很多钱。。。否则你会在那里呆上几个星期。此外,如果您的网络中有多台计算机GNU并行也可以在它们之间分配作业和数据,以加快速度。

因此,假设需要处理的文件都以*.OK结束,一个基本的例子是:

parallel -k echo {#} {.} ::: ads123.OK qwe987.OK tyu456.OK

将输出以下内容:

1 ads123
2 qwe987
3 tyu456

所以希望您能看到{#}只是顺序增加的作业编号,而{.}是删除了扩展名的文件名。

好吧,现在你想在开始工作之前处理一下你的参数文件,所以你最好为每个预处理的工作写一个bash函数,就像这样。我将调用函数doit():

doit(){
jobnum=$1
name=$2
paramfile="parameters.$jobnum"
echo Processing file: $name with parameters in file: $paramfile
}
# Make our function known to jobs started by GNU Parallel
export -f doit
# Now run the jobs
parallel -k doit {#} {.} ::: *.OK

现在我们所需要做的就是更改doit()来准备您的参数,这样我们就可以做到:

doit(){
jobnum=$1
name=$2
paramfile="parameters.$jobnum"
echo Processing file: $name with parameters in file: $paramfile
# Following code supplied by @poshi
echo "input_file = $name"          >  "$paramfile
echo "input_file2 = $name.TXT"     >> "$paramfile"
echo "outfile = $name.RESULTS_OUT" >> "$paramfile"
# Add/copy/incorporate the rest of the parameters as you wish
echo program "$paramfile"
}

在进程替换中使用printf,不要麻烦替换parameters_file.txt中的字符串。

for f in *.OK; do
prog <(
printf 'input_file = %sninput_file2 = %snoutfile = %sn' "${f%OK}"{OK,TXT,RESULTS_OUT}
tail -n +4 parameters_file.txt
)
done

执行创建输入参数文件和的循环,运行程序:

for f in *.OK;
do
echo "input_file = $f" > parameters
"input_file2 = $f.TXT" >> parameters
"outfile = $f.RESULTS_OUT" >> parameters
# Add/copy/incorporate the rest of the parameters as you wish
./program parameters
done

我想这样的东西会达到你想要的:

#!/bin/bash
for file in *.OK; do
sed -i 
-e "s/input_file =.*/input_file = ${file}/"  
-e "s/input_file2.*/input_file2 = ${file%.OK}.TXT/" 
-e "s/outfile.*/outfile = ${file%.OK}.RESULTS_OUT/" 
parameters_file.txt
./program parameters_file.txt 
done

最新更新