naoki86star

インターネットの片隅でなにかしら書いてみる

touchコマンドの-rオプション

jacksonというjsonライブラリを使っていてシリアライズしたテキストをファイルに保存していたとき、TRUNCATE_EXISTINGをつけ忘れて、上書き時に元のテキスト長より短かった時に、末尾に前のテキストが残ってしまっていた。

書き込んだファイルの読み取りではjackson readTreeというメソッドつかってシリアライズしていた。これだとエラーと言われず期待通りに読み込まれていて気づかなかった。pythonのjson#load(s)では例外が上がってきてようやく気が付いた。

{ "key": "value" }}

とか

{ "key": "value" }lue" }

みたいな

すでに多数の作業ファイルをjson保存してしまっていて、速攻brokenなjsonファイルを修正する必要があった。

このときファイル時刻をキープしておきたいという自分の要件がつく。

jacksonはエラーなしで読み込んでくれるのだからその延長上で、なんかしらの修正プログラム書けばいい。けども一発タスクの処理をjavaで書く気はおきない。

それをいつもだとpythonに頼るのだけどもすぐにできなくて、シェルスクリプト(jqコマンド+touch)でやりました。*1
*2

for oldfile in `ls`
do
newfile=$oldfile.new
jq -c . $oldfile 2>/dev/null >$newfile
touch -r $oldfile $newfile
done

jqが警告が標準エラー出力にでるがそれを無視すれば読み込んでくれる。
*3

touchコマンドが新しい気づき。第2引数ファイルのstatを第三引数のファイルにtouchしてくれる。こんなオプションがあったのかぁ。

*1:pythonでも余計なテキストを除去する処理を速攻書けばいいのだけどもちょっともたつきそうだったので。思いついたのは、例外が起きたら一文字づつ末尾をトランケートして成功するまでjson.loadsを繰り返す、とか程度しか思いついてない。

*2:json.loads()にエラーを無視して読めるものは読むというオプションがないかどうか調べてみたけど、ない、と判断した

*3:もし”余計な"テキストが"正しい"jsonテキストで残っているようなケースではjqは順次処理して出力してしまう。"{}"がくっついているとか。今回のミスでそういう壊れ方にはならない、なかった