循环覆盖文件

时间:2020-02-29 15:59:02

标签: bash

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

./program parameters_file.txt

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

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

如图所示,所有文件都具有匹​​配的名称,并且只有其扩展名更改。

我需要循环执行此操作,以便每次循环重新启动时都会覆盖input_file,input_file2和outfile。诸如此类:用第一个文件名编辑parameters_file.txt,在第一个文件上运行命令,用第二个文件名编辑parameter_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覆盖?

谢谢。

4 个答案:

答案 0 :(得分:2)

执行一个创建输入参数文件的循环,然后运行程序:

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

答案 1 :(得分:2)

我想这样的事情会实现您想要的:

#!/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

答案 2 :(得分:2)

在进程替换中使用printf,不必为替换parameters_file.txt中的字符串而烦恼。

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

答案 3 :(得分:2)

如果要处理数千个文件,每个文件要花费一个小时,则可以考虑使用 GNU Parallel 并行完成4、8或16个操作,并使所有CPU内核忙于处理您付给英特尔如此丰厚的报酬...否则您将在那里待上数周。另外,如果您的网络中有多台计算机, GNU Parallel 也可以在它们之间分配作业和数据,以加快处理速度。

因此,假设您需要处理的所有文件都以*.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"
}