親フォルダ内には多くのサブフォルダがあり、各サブフォルダ内にはログファイルがあります。ログファイルには、次のような多くのデータがあります。
> Rotational constants (GHZ): 0.0423083 0.0029364
> 0.0027927 Standard basis: 6-31G(d,p) (6D, 7F) There are 1566 symmetry adapted cartesian basis functions of A symmetry. There are
> 1566 symmetry adapted basis functions of A symmetry. 1566 basis
> functions, 3052 primitive gaussians, 1566 cartesian basis functions
> 355 alpha electrons 355 beta electrons
> nuclear repulsion energy 15971.0567247177 Hartrees. NAtoms= 130 NActive= 130 NUniq= 130 SFac= 1.00D+00 NAtFMM= 60
> NAOKFM=T Big=T Integral buffers will be 131072 words long.
> Raffenetti 2 integral format. Two-electron integral symmetry is
> turned on. One-electron integrals computed using PRISM. NBasis=
> 1566 RedAO= T EigKep= 2.31D-04 NBF= 1566 NBsUse= 1566 1.00D-06
> EigRej= -1.00D+00 NBFU= 1566 Initial guess from the checkpoint file:
> > 0.000000 0.000000 0.000000
> Rot= 1.000000 -0.000006 0.000001 -0.000001 Ang= 0.00 deg. Requested convergence on RMS density matrix=1.00D-08 within 128 cycles. Requested convergence on MAX density matrix=1.00D-06.
> Requested convergence on energy=1.00D-06. No special
> actions if energy rises. SCF Done: E(RB3LYP) = -8526.66394979
> A.U. after 6 cycles
> NFock= 6 Conv=0.72D-08 -V/T= 2.0055 Calling FoFJK, ICntrl= 2127 FMM=T ISym2X=0 I1Cent= 0 IOpClX= 0 NMat=1 NMatS=1
> NMatT=0.
たとえば、SCF Done: E(RB3LYP) = -8526.66394979
上記のテキストを見ています。=
各ファイルの変更された値。私にとって必要なのは、すべての値を抽出して親フォルダのテキストファイルに入れることです。たとえば、bar、baz、fooという3つのフォルダがあります。今、次の結果が必要です。
bar : -8526.66394979
baz : -112232.123391
foo : 12312313:34574
次のスクリプトを実行すると、1つの値しか持たなくなります(例:-8526.66394979)。この問題を解決するのに役立ちますか?
#!/bin/bash
for file_name in *
do
cd $file_name
EE=$(grep -i 'scf done' *.log | tail -1 | awk 'NR==1 {print $5}')
echo "Electronic Energy : $EE" | column -t -s ":" > ${file_name%%.*}.txt
mv ${file_name%%.*}.txt ../
done
答え1
ディレクトリごとに1つのログファイルだけがあり、そのログファイルの最後の値を保持し、それをディレクトリ名とともにテキストファイルに保存する場合は、次のことを実行できます。
for dir in */; do
grep -i 'scf done' "$dir"/*.log |
awk 'END{print "Electronic Energy : "$5}' |
column -t -s ":" > "${dir///}".txt
done
たとえば、次の設定を使用しました。
$ tree
.
├── dir1
│ └── file.log
├── dir10
│ └── file.log
├── dir2
│ └── file.log
├── dir3
│ └── file.log
├── dir4
│ └── file.log
├── dir5
│ └── file.log
├── dir6
│ └── file.log
├── dir7
│ └── file.log
├── dir8
│ └── file.log
└── dir9
└── file.log
それぞれはfile.log
以下を含んでいます:
$ cat dir1/file.log
a b scf done 123
for
上記のループを実行すると、次のような結果が発生します。
$ ls *txt
dir10.txt dir1.txt dir2.txt dir3.txt dir4.txt dir5.txt dir6.txt dir7.txt dir8.txt dir9.txt
各項目には以下が含まれます。
$ cat dir1.txt
Electronic Energy 123
それでも問題が解決しない場合は、質問を更新し、関連するディレクトリ構造、ファイル名、サンプル入力、予想される出力を表示してください。
答え2
私はこれを準備しました:
#!/bin/bash
for dir in */; do
grep -i 'scf done' "$dir"/*.log |
awk 'END{print ""$5}'|
column -t -s ":" > "${dir///}".tmp
done
for file_name in *.tmp
do
echo "${file_name%%.*} : "
cat "$file_name"
done > tmp
awk 'NR%2{printf "%s ",$0;next;}1' tmp > tmp2
sort -k 3 tmp2 > Energy.txt
rm *.tmp tmp tmp2
cat Energy.txt
それは動作し、必要なすべてをカバーしています。しかし、私は動作できるコマンドを使用してコーディングする高レベルの方法を探しています。
答え3
ディレクトリ構造を正しく理解して再現することを願っています。以下を試してください。
awk '/SCF Done/ {print FILENAME ": " $NF}' */*.log
bar/b1.log: -8526.66394979
baz/b2.log: -7777777.22222
baz/b2.log: -112232.123391
foo/f3.log: -7777777.22222
foo/f3.log: 12312313.34574
ディレクトリだけが必要な場合は、結果配列の最初の要素をsplit
使用してください。FILENAME
各ファイルの最後のエントリだけが必要な場合は、次の手順を試してください。
awk '/SCF Done/ {print FILENAME ": " $NF}' */*.log | tac | sort -u -k1,1
bar/b1.log: -8526.66394979
baz/b2.log: -112232.123391
foo/f3.log: 12312313.34574
で整理するよりも、これは簡単で簡単ですawk
。