平均并移动选定的文件

平均并移动选定的文件

我有一堆目录,每个目录都包含一个与目录名称相应命名的 ascii 表;如下:

a1/a1.txt
a2/a2.txt
a3/a3.txt
a4/a4.txt
b1/b1.txt
b2/b2.txt
b3/b3.txt
b4/b4.txt

我想通过计算每个文件第四列的平均值(so )和(so )来操作4个不同文件的a选择;然后将平均值最高的表移动到另一个目录。baa1.txt a2.txt a3.txt a4.txtbb1.txt b2.txt b3.txt b4.txt

因此,如果:

a1.txt average value = 1
a2.txt average value = 0.25
a3.txt average value = 2
a4.txt average value = 1.15
b1.txt average value = 3
b2.txt average value = 1.7
b3.txt average value = 0.25
b4.txt average value = 2

然后a3.txtb1.txt应移动到远程目录。

我有以下代码:

for x in a b
do
  RESULT=$(awk '{x+=$4} END{print x/NR, FILENAME}' ${x}[1-4]/${x}[1-4].txt | sort -n -r| head -1)
  highest="$(echo $RESULT | cut -d ' ' -f1 )"
  hifile="$(echo $RESULT | cut -d ' ' -f2 )"
  echo "highest was $highest in $hifile"
  cp "$hifile" "high_dis/${x}.txt"
done

但这段代码只是计算四个文件的平均值,然后复制最后一个文件(a4.txtb4.txt

有谁知道如何获得所需的输出?

答案1

你的问题是由于以下事实仅在读取所有输入文件后,awk 才会到达 END 子句

将循环的第一行替换for为以下内容即可解决您的问题。

RESULT=$(awk 'BEGIN{curr_f=FILENAME; nr=1} {if(curr_f!=FILENAME){if(mean > max_mean){max_mean=mean; f=curr_f} curr_f=FILENAME; nr=0; sum=0} } { sum+=$4; nr++; mean=sum/nr }  END{if(mean>max_mean){print mean, FILENAME}else{print max_mean, f}}' ${x}[1-4]/${x}[1-4].txt )

答案2

我会使用稍微不同的方法,直接在 awk 中完成更多工作。首先,使用FNR每次处理新文件时返回到 1 的,并立即awk将所有 a- 或 b- 文件提供给:awk

$ for f in a b; do 
    awk '(FNR==1 && n>1){
            av=x/n;if(av>max){
                max=av;f=FILENAME
            }
        x=0; n=0
        }
        {x+=$4;n=FNR} 
        END{ 
            if(x/n>max){print x/n,FILENAME}
            else{print max,f}'
        } "$f"[1..4]/"$f"[1..4].txt; done
18898.4 a3.txt
18806 b4.txt

这为我们提供了具有最大平均值的两个文件。要移动它们,您可以简单地从先前脚本的输出中删除该值,仅保留文件名并将其直接传递给命令cp

$ cp -v $(for f in a b; do awk '(FNR==1 && n>1){av=x/n;if(av>max){max=av;f=FILENAME};x=0;n=0}{x+=$4;n=FNR} END{if(x/n>max) print x/n,FILENAME; else print max,f}' "$f"[1-4]/"$f"[1..4].txt; done) bar/
‘a3.txt’ -> ‘bar/a3.txt’
‘b4.txt’ -> ‘bar/b4.txt’

请注意,如果您的文件名包含空格或通配符,这将会中断。

相关内容