みなさん、こんにちは。
今回はまず「c.ファイル名複数指定」です。こんな形に対応します。
複数指定なので、#argument
でテンプレートを取得できる限り「a.ファイル名にワイルドカードを指定」の処理を無限に繰り返せばいいのです。繰り返しは #LOOP built-in function
でしたね。既にワイルドカードの展開で #LOOP
を使っていますので、二重ループを構成することになります。
イメージ的には
[#loop |do| [#loop |do| ---> この #loop 内が今の fl マクロの処理 ワイルドカード展開 |until| ワイルドカードが展開できない ] 次のパラメータ取得 |until| END にヒット ]
という感じです。ほんの数行の追加で済みます。簡単ですね。
?section fl routine
#push fn1 fn2 sb2 ts1 ts2 err tmp breakvol arg
#push yyyy mm dd hh mmm ss ms us
[#if [#argument/value tmp/TEMPLATE END] = 2 |then|
#set tmp *
]
#set breakvol ----
[#loop |do|
#set fn1 [#filenames/maximum 1/ [tmp]]
[#loop |while| NOT [#EMPTYV fn1] |do|
#set fn2 [#fileinfo/file/[fn1]]
#set sb2 [#fileinfo/volume/[fn1]].[#fileinfo/subvol/[fn1]]
#set ts1 [#fileinfo /LASTOPEN_GMT/[:fn1]]
#setmany err ts2,[#CONVERTTIMESTAMP [ts1] 0]
#setmany _ yyyy mm dd hh mmm ss ms us,[#interprettimestamp [ts2]]
[#if breakvol '<>' sb2 |then|
#output
#output [sb2]
#output /width 18,hold/
#output LAST OPEN
#set breakvol [sb2]
]
#output /width 18,hold/ [fn2]
#output /width 5,hold,fill zero,justify right/ [yyyy]/
#output /width 3,hold,fill zero,justify right/ [mm]/
#output /width 2,hold,fill zero,justify right/ [dd]
#output /width 1,hold,fill space/
#output /width 3,hold,fill zero,justify right/ [hh]:
#output /width 3,hold,fill zero,justify right/ [mmm]:
#output /width 3,hold,fill zero,justify right/ [ss].
#output /width 3,hold,fill zero,justify right/ [ms]
#output /width 3 ,fill zero,justify right/ [us]
#set fn1 [#filenames/maximum 1, previous [fn1]/ [tmp]]
]
#set arg [#argument/value tmp/TEMPLATE END]
|until| arg = 2
]
#pop yyyy mm dd hh mmm ss ms us
#pop fn1 fn2 sb2 ts1 ts2 err tmp breakvol arg
追加した
#set arg [#argument/value tmp/TEMPLATE END]
|until| arg = 2
は、上記のイメージに沿って2行で書いていますが、実は1行でも書けてしまいます。
|until| [#argument/value tmp/TEMPLATE END] = 2
arg variable
を使わずにすむので、こちらの方がいいですね。それでこうなります。
?section fl routine
#push fn1 fn2 sb2 ts1 ts2 err tmp breakvol
#push yyyy mm dd hh mmm ss ms us
[#if [#argument/value tmp/TEMPLATE END] = 2 |then|
#set tmp *
]
#set breakvol ----
[#loop |do|
#set fn1 [#filenames/maximum 1/ [tmp]]
[#loop |while| NOT [#EMPTYV fn1] |do|
#set fn2 [#fileinfo/file/[fn1]]
#set sb2 [#fileinfo/volume/[fn1]].[#fileinfo/subvol/[fn1]]
#set ts1 [#fileinfo /LASTOPEN_GMT/[:fn1]]
#setmany err ts2,[#CONVERTTIMESTAMP [ts1] 0]
#setmany _ yyyy mm dd hh mmm ss ms us,[#interprettimestamp [ts2]]
[#if breakvol '<>' sb2 |then|
#output
#output [sb2]
#output /width 18,hold/
#output LAST OPEN
#set breakvol [sb2]
]
#output /width 18,hold/ [fn2]
#output /width 5,hold,fill zero,justify right/ [yyyy]/
#output /width 3,hold,fill zero,justify right/ [mm]/
#output /width 2,hold,fill zero,justify right/ [dd]
#output /width 1,hold,fill space/
#output /width 3,hold,fill zero,justify right/ [hh]:
#output /width 3,hold,fill zero,justify right/ [mmm]:
#output /width 3,hold,fill zero,justify right/ [ss].
#output /width 3,hold,fill zero,justify right/ [ms]
#output /width 3 ,fill zero,justify right/ [us]
#set fn1 [#filenames/maximum 1, previous [fn1]/ [tmp]]
]
|until| [#argument/value tmp/TEMPLATE END] = 2
#pop yyyy mm dd hh mmm ss ms us
#pop fn1 fn2 sb2 ts1 ts2 err tmp breakvol
さあ、最後です。「d.作成日時や更新日時にも対応」を実装します。d. の要求仕様は次の通りでした。
d. の要求仕様から、最初のパラメータは TEMPLATE END
に加えて SLASH
を許容しなければなりません。1番目のパラメータが SLASH
にヒットしたということは /OPEN/
、/CREATE/
、 /MOD/
のどれかということですので、2番目のパラメータは KEYWORD
オプションで OPEN
、CREATE
、 MOD
のいずれかに制限して取り込みます。最後の閉じる /
も忘れないようにしましょう。
[#case [#argument/value tmp/SLASH TEMPLATE END] |1| sink [#argument/value func/KEYWORD/WORDLIST OPEN CREATE MOD/] sink [#argument/value tmp/SLASH] [#if [#argument/value tmp/TEMPLATE END] = 2 |then| #set tmp * ] |3| #set tmp * ]
という感じになります。閉じる /
の後にもう一度 TEMPLATE END
の検査をしているのがミソです。タイムスタンプ取得の部分はオプションに応じた改造が必要です。
[#case [func] |OPEN| #set ts1 [#fileinfo /LASTOPEN_GMT/[:fn1]] #setmany err ts2,[#CONVERTTIMESTAMP [ts1] 0] |CREATE| #set ts1 [#fileinfo /CREATION_GMT/[:fn1]] #setmany err ts2,[#CONVERTTIMESTAMP [ts1] 0] |MOD| #set ts1 [#fileinfo /MODIFICATION_LCT/[:fn1]] #set ts2 [ts1] ]
MODIFICATION_LCT
は JST
なので #CONVERTTIMESTAMP
が不要ということに注意してください。
以上が要求仕様に基づく変更点ですが、今まで説明していない注意事項が1点ありますのでそれも考慮に入れることにしましょう。
fup create
でファイルを作成した直後等、ファイルは実在していてもオープンされたことが一度もない、ということがあります。このようなファイルに対する #fileinfo /LASTOPEN_GMT/
の戻り値はゼロになります。このため
#setmany err ts2,[#CONVERTTIMESTAMP [ts1] 0]
がエラーになって ts2
に値が入らず #interprettimestamp
で時刻に展開できません。この場合の処理も追加する必要があります。
以上をすべて反映すると、ソースは次のようになります。
?section fl routine #push fn1 fn2 sb2 ts1 ts2 err tmp func breakvol title #push yyyy mm dd hh mmm ss ms us [#case [#argument/value tmp/SLASH TEMPLATE END] |1| sink [#argument/value func/KEYWORD/WORDLIST OPEN CREATE MOD/] sink [#argument/value tmp/SLASH] [#if [#argument/value tmp/TEMPLATE END] = 2 |then| #set tmp * ] |2| #set func OPEN |3| #set tmp * #set func OPEN ] #set breakvol ---- [#loop |do| #set fn1 [#filenames/maximum 1/ [tmp]] [#loop |while| NOT [#EMPTYV fn1] |do| #set fn2 [#fileinfo/file/[fn1]] #set sb2 [#fileinfo/volume/[fn1]].[#fileinfo/subvol/[fn1]] [#case [func] |OPEN| #set ts1 [#fileinfo /LASTOPEN_GMT/[:fn1]] #setmany err ts2,[#CONVERTTIMESTAMP [ts1] 0] #set title LAST OPEN |CREATE| #set ts1 [#fileinfo /CREATION_GMT/[:fn1]] #setmany err ts2,[#CONVERTTIMESTAMP [ts1] 0] #set title CREATED |MOD| #set ts1 [#fileinfo /MODIFICATION_LCT/[:fn1]] #set ts2 [ts1] #set title LAST MODIFIED ] [#if breakvol '<>' sb2 |then| #output #output [sb2] #output /width 18,hold/ #output [title] #set breakvol [sb2] ] #output /width 18,hold/ [fn2] [#if [#emptyv ts2] |then| #output NEVER OPENED |else| #setmany _ yyyy mm dd hh mmm ss ms us,[#interprettimestamp [ts2]] #output /width 5,hold,fill zero,justify right/ [yyyy]/ #output /width 3,hold,fill zero,justify right/ [mm]/ #output /width 2,hold,fill zero,justify right/ [dd] #output /width 1,hold,fill space/ #output /width 3,hold,fill zero,justify right/ [hh]: #output /width 3,hold,fill zero,justify right/ [mmm]: #output /width 3,hold,fill zero,justify right/ [ss]. #output /width 3,hold,fill zero,justify right/ [ms] #output /width 3 ,fill zero,justify right/ [us] ] #set fn1 [#filenames/maximum 1, previous [fn1]/ [tmp]] ] |until| [#argument/value tmp/TEMPLATE END] = 2 ] #pop yyyy mm dd hh mmm ss ms us #pop fn1 fn2 sb2 ts1 ts2 err tmp func breakvol title
ずいぶん長いソースになってきましたね。説明していない細かい修正も入れています。技術的に新しい要素は特にないので、みなさんでチェックしてみてください。個人的にはこの fl
マクロから派生させたものをよく使っています。みなさんも各自の業務に合わせて改造していってください。
え、なんですか。長いソースのくせにコメントの1つもない?そうですか、コメントを入れたいですか。コメントは次のように入れます。
察してもらえると思いますが、==
は行の最後まで全部がコメントで、{}
は囲った間だけがコメントになります。単純にこんな書き方もできます。
comment
はパラメータを読み捨てているだけの routine
です。読み捨てると言えばこんなのもありましたね。
これでコメントを書くことはまずないでしょうけど。適切なコメントは好感度アップの秘訣です。センスを発揮してくださいね。
さて、長かった fl マクロも今回でおしまいです。次回はまた違う課題を取りあげましょう。Au revoir!