查找子目录中的最大值和最小值(使用shell脚本少于10秒)

时间:2013-11-30 14:43:50

标签: linux performance shell command pipeline

我有几个这种类型的文件:

Sensor   Location              Temp       Threshold
------   --------              ----       ---------
#1        PROCESSOR_ZONE       23C/73F    62C/143F 
#2        CPU#1                30C/86F    73C/163F 
#3        I/O_ZONE             32C/89F    68C/154F 
#4        CPU#2                22C/71F    73C/163F 
#5        POWER_SUPPLY_BAY     17C/62F    55C/131F 

在几个子目录中大约有124630个 我尝试确定PROCESSOR_ZONE的最高和最低温度 这是我的脚本:

#!/bin/bash

max_value=0
min_value=50

find $1 -name hp-temps.txt -exec grep "PROCESSOR_ZONE" {} + | sed -e 's/\ \+/,/g' | cut -d, -f3 | cut -dC -f1 | while read current_value ; 
do
    echo $current_value;
done

在我的脚本之后输出:

30
28
26
23
...

我的脚本没有完成,它会设置10分钟来显示所有温度。 我认为要到达那里,我必须将我的命令结果放在一个文件中,整理出来并返回第一行,即最大值,最后一行是最小值。但我不知道该怎么做。

3 个答案:

答案 0 :(得分:0)

而不是这一点:

... | while read current_value ;
do
    echo $current_value;
done

只需将cut之后的输出定向到文件:

... > temperatures.txt

如果您需要对它们进行排序,请先对它们进行排序:

... | sort -n > temperatures.txt

然后文件的第一行将返回最低温度,最后一行将是最高温度。

表现建议:

find命令在每个文件上运行新的grep进程。如果您的目录中有数十万个这样的文件,它将运行grep数十万次。您可以通过告诉find为每批几千个文件运行一次grep命令来加快速度:

find $1 -name hp-temps.txt -print | xargs grep -h "PROCESSOR_ZONE" | sed ...

find命令在标准输出上输出文件名; xargs命令读取这些内容并立即对一批文件运行grep。 grep的-h选项意味着“不要在输出中包含文件名”。

如果要处理数千个文件,以这种方式运行应该可以大大加快搜索速度。

答案 1 :(得分:0)

如果你的脚本很慢,你可能想先分析哪个命令很慢。使用find例如Windows / Cygwin包含大量文件会很慢。

Perl非常适合您的问题:

find $1 -name hp-temps.txt -exec perl -ne '/PROCESSOR_ZONE\s+(\d+)C/ and print "$1\n"' {} +

通过这种方式,您可以同时对许多文件执行(Perl)正则表达式匹配。括号与温度数字(\d+)和$1引用相匹配。 and确保在匹配成功时执行仅打印。

您甚至可以考虑使用opendirreaddir递归下降到Perl中的目录以摆脱查找,但它不会更快。


获取最小值和最大值:

    find $1 -name hp-temps.txt -exec perl -ne 'if (/PROCESSOR_ZONE\s+(\d+)C/){ $min=$1 if $1<$min or $min == undef; $max=$1 if $1>$max }; sub END { print "$min - $max\n" }' {} +

终端上有100k +输出线,这样可以节省很多时间。

答案 2 :(得分:0)

#!/bin/bash

max_value=0
min_value=50

find $1 -name file.txt -exec grep "PROCESSOR_ZONE" {} + | sed -e 's/\ \+/,/g' | cut -d, -f3 | cut -dC -f1 |
{
while read current_value ; do
    #For maximum
    if [[ $current_value -gt $max_value ]]; then
        max_value=$current_value
    fi

    #For minimum
    if [[ $current_value -lt $min_value ]]; then
        min_value=$current_value
    echo "new min $min_value"
    fi
done

echo "NEW MAX : $max_value °C"
echo "NEW MIN : $min_value °C"
}