将结果文件重定向到不同的变量文件名

时间:2016-03-06 08:46:01

标签: bash

我有一个文件夹,比如十个数据文件I01.txt,...,I10.txt ..每个文件,当使用命令/a.out执行时,会给我五个输出文件,即f1.txtf2.txt,... f5.txt

我编写了一个简单的bash程序来执行所有文件,并使用命令将打印在屏幕上的输出保存到变量文件中

./ cosima_peaks_444_temp_muuttuva  -args > $counter-res.txt. 

使用此功能,我可以将屏幕输出保存到文件中。但是,f1f5的五个文件被更改为存储上次运行文件的结果,在本例中为I10,前九个文件的结果将丢失。

所以我想将每个I*.txt文件(f1 ... f5)的输出保存到一个不同的文件中,以便在程序执行I01.txt时,使用./a.out它存储文件的输出

f1>var1-f1.txt ,    f2>var1-f2.txt... f5 > var1-f5.txt 

然后为I02f1>var2-f1.txt ...)重复相同的内容。

#!/bin/bash

# echo "for looping over all the .txt files"
echo -e "Enter the name of the file or q to quit "
read dir
if [[ $dir = q ]]
then        
    exit
fi

filename="$dir*.txt"
counter=0

if [[ $dir == I ]]
then
    for f in $filename ; do
        echo "output of $filename"
        ((counter ++))
        ./cosima_peaks_444_temp_muuttuva $f -m202.75 -c1 -ng0.5 -a0.0 -b1.0 -e1.0 -lg > $counter-res.txt 
        echo "counter $counter"
    done
fi

3 个答案:

答案 0 :(得分:0)

如果我了解您要将文件l01.txtl02.txt,...传递给a.out,并将a.out的每次执行的输出保存到单独的文件中,例如f01.txtf02.txt,...,然后您可以使用一个简短的脚本来读取目录中名为l*.txt的每个文件,并将值传递给a.out,将输出重定向到文件fN.txtNlN.txt文件名中的号码相同。)这假设您将每个文件名传递给a.out,而a.out不是自动读取整个目录。

for i in l*.txt; do 
    num=$(sed 's/^l\(.*\)[.]txt/\1/' <<<"$i")
    ./a.out "$i" > "f${num}.txt"
done

注意:'s/(lowercase L) ... /\one..'

注意:如果您不希望文件名相同N(其前导'0'),那么您可以修剪前导'0'输出文件名的N值。

(您可以使用已编辑的帖子中显示的counter,但除非您明确对它们进行排序,否则您无法保证循环使用的文件名的排序顺序)

注意:,这假设文件名中没有spaces或嵌入式newline或其他奇数字符。如果您的lN.txt名称可以包含奇数字符或空格,那么使用while提供find循环可以避免出现奇怪的字符问题。

使用f1 - f5创建每次运行

您知道输出文件名的格式,因此您可以测试是否存在现有文件名,并设置前缀后缀以提供唯一名称。例如,如果您的第一次传递创建了文件名'pass1-f01.txt''pass1-f02.txt',那么您可以检查该模式(以多种方式)并根据需要增加'passN'前缀:

for f in "$filename"; do 
    num=$(sed 's/l*\(.*\)[.]txt/\1/' <<<"$f")
    count=$(sed 's/^0*//' <<<"$num")
    while [ -f "pass${count}-f${num}.txt" ]; do
        ((count++))
    done
    ./a.out "$f" > "pass${count}-f${num}.txt"
done

尝试一下,让我知道这是否与您的需求不相符。

注意: herestring <<<)的使用仅限bash,如果需要便携式解决方案,请输出{{{ 1}}到echo "$var",例如sed

答案 1 :(得分:0)

我猜你有这个a.out二进制文件的源代码。如果是这样,我会修改它,以便输出到几个fds而不是几个文件。然后你可以使用重定向非常干净地解决这个问题:

./a.out 3> fileX.1 4> fileX.2 5> fileX.3

依此类推您要输出的每个文件。写入文件或(重定向)fd在大多数程序中都是等效的(值得注意的例外:内存映射I / O,但这种脚本不常用 - 查找mmap个调用)

请注意,这不是很深奥,而是一种众所周知的技术,通常用于将输出(stdout,fd = 1)与错误(stderr,fd = 2)分开。

答案 2 :(得分:0)

我将cosima_peaks_444_temp_muuttuva替换为function myprog。 OP要求更多解释,所以我发表了很多评论:

# This function makes 5 output files for testing the construction
function myprog {
   # Fill the test output file f1.txt with the input filename and a datestamp
   echo "Output run $1 on $(date)" > f1.txt
   # The original prog makes 5 output files, so I copy the new testfile 4 times
   cp f1.txt f2.txt
   cp f1.txt f3.txt
   cp f1.txt f4.txt
   cp f1.txt f5.txt
}

# Use the number in the inputfile for making a unique filename and move the output
function move_output {
   # The parameter ${1} is filled with something like I03.txt
   # You can get the number with a sed action, but it is more efficient to use
   # bash functions, even in 2 steps. 
   # First step: Cut off from the end as much as possiple (%%) starting with a dot.
   Inumber=${1%%.*}
   # Step 2: Remove the I from the Inumber (that is filled with something like "I03").
   number=${Inumber#I}
   # Move all outputfiles from last run
   for outputfile in f*txt; do
      # Put the number in front of the original name
      mv "${outputfile}" "${number}_${outputfile}"
   done
}

# Start the main processing. You will perform the same logic for all input files,
# so make a loop for all files. I guess all input files start with an "I",
# followed by 2 characters (a number), and .txt. No need to use ls for listing those.

for input in I??.txt; do
   # Call the dummy prog above with the name of the first input file as a parameter
   myprog "${input}"
   # Now finally the show starts.
   # Call the function for moving the 5 outputfiles to another name.
   move_output "${input}"
done