
という名前の数十万のファイルを含むフォルダhp-temps.txt
(および多数のサブフォルダ)があります。
そのファイルの内容は次のとおりです。
Sensor Location Temp Threshold
------ -------- ---- ---------
#1 PROCESSOR_ZONE 15C/59F 62C/143F
#2 CPU#1 10C/50F 73C/163F
#3 I/O_ZONE 25C/77F 68C/154F
#4 CPU#2 32C/89F 73C/163F
#5 POWER_SUPPLY_BAY 9C/48F 55C/131F
すべてのファイルを解析し、ライン#1で最も高い温度項目を見つける必要があります。
作業中のスクリプトがありますが、時間がかかり、それを改善する方法があるかどうかを知りたいです。
私はシェルスクリプトに初めて触れたので、このコードは本当に非効率的だと思います。
#!/bin/bash
highesetTemp=0
temps=$(find $1 -name hp-temps.txt -exec cat {} + | grep 'PROCESSOR' | cut -c 32-33)
for t in $temps
do
if [ $t -gt $highestTemp ]; then
highestTemp=$t
fi
done
編集する:
非常に効率的なコードがありますが、最大の値しか必要としないことに言及することを忘れていました。
より高い値が検出されたら、ファイルのディレクトリと温度を出力したいので、すべてのファイルを繰り返すことができます。
したがって、出力は次のようになります。
New MAX: 22 in /path/to/file/hp-temps.txt
New MAX: 24 in /another/path/hp-temps.txt
New MAX: 29 in /some/more/path/hp-temps.txt
答え1
中間データを文字列として保存するのは遅く、ほとんど必要ありません。通常、単一のスカラー変数に複数の文字列を格納することには、追加の問題があります。このように、各部分文字列にはスペースやその他の文字を含めることができ、後で引用符なしでループ方式を使用してシェルを強制的に解決できます。文字列を分割しますfor
(配列を使用する方が良いです)。
この場合、各ファイルを見つけて温度を抽出し、その温度ストリームを読み取る方が効率的です。また、300 KB(またはそれ以上)の文字列を含むシェル変数の生成を防ぎます。
摂氏温度は以下で分析できます。一つファイル使用量
awk '$2 == "PROCESSOR_ZONE" { printf "%d\n", $3 }' file
2番目のフィールドが文字列の場合、3番目のフィールドの温度を出力しますPROCESSOR_ZONE
。書き込み時に3番目のフィールドが整数に変換されるため、値の最初の部分だけが出力されます(数字ではなく最初の部分まで)。
以下から呼び出されますfind
。
find . -name hp-temps.txt \
-exec awk '$2 == "PROCESSOR_ZONE" { printf "%d\n", $3 }' {} +
これはawk
、見つかったファイルの1つ以上のバッチに対してコマンドを実行し、標準出力に順番に温度を出力します。
awk
非標準ステートメントを理解することを使用している場合は、nextfile
それを使用してできるだけ早く次のファイルに移動できます。
find . -name hp-temps.txt \
-exec awk '$2 == "PROCESSOR_ZONE" { printf "%d\n", $3; nextfile }' {} +
上記のコマンドで出力された最大値を見つけるには、次のawk
コマンドを使用することもできます。
awk 'NR == 1 || $1 > max { max = $1 } END { print max }'
awk
max
変数の値がこれまでに確認された最初の値または最大値の場合は、現在の入力値に設定します。最後のmax
出力値です。
私はこれがシェルループよりも数倍速いと思います。
総合してみると:
find . -name hp-temps.txt \
-exec awk '$2 == "PROCESSOR_ZONE" { printf "%d\n", $3; nextfile }' {} + |
awk 'NR == 1 || $1 > max { max = $1 } END { print max }'
最大値を持つファイルのファイル名を検索するための追加の要求があります。各ファイルの値とともにファイル名を渡すだけです。では、awk
現在の入力ファイルのパス名を特殊変数として使用できますFILENAME
。
find . -name hp-temps.txt \
-exec awk '$2 == "PROCESSOR_ZONE" { printf "%d\t%s\n", $3, FILENAME; nextfile }' {} + |
awk 'NR == 1 || $1 > max { max = $1; fname = $2 } END { print max, fname }'
複数のファイルの最大値が等しい場合、見つかった最初のファイルのファイル名が報告されますfind
。ユーティリティは、find
リストされた順序でファイルを検索します。ls -f