我有一个文件夹,比如十个数据文件I01.txt
,...,I10.txt
..每个文件,当使用命令/a.out
执行时,会给我五个输出文件,即f1.txt
,f2.txt
,... f5.txt
。
我编写了一个简单的bash程序来执行所有文件,并使用命令将打印在屏幕上的输出保存到变量文件中
./ cosima_peaks_444_temp_muuttuva -args > $counter-res.txt.
使用此功能,我可以将屏幕输出保存到文件中。但是,f1
到f5
的五个文件被更改为存储上次运行文件的结果,在本例中为I10
,前九个文件的结果将丢失。
所以我想将每个I*.txt
文件(f1
... f5
)的输出保存到一个不同的文件中,以便在程序执行I01.txt
时,使用./a.out
它存储文件的输出
f1>var1-f1.txt , f2>var1-f2.txt... f5 > var1-f5.txt
然后为I02
(f1>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
答案 0 :(得分:0)
如果我了解您要将文件l01.txt
,l02.txt
,...传递给a.out
,并将a.out
的每次执行的输出保存到单独的文件中,例如f01.txt
,f02.txt
,...,然后您可以使用一个简短的脚本来读取目录中名为l*.txt
的每个文件,并将值传递给a.out
,将输出重定向到文件fN.txt
(N
与lN.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