FileMaker Pro で画像や映像のメディアを管理するデータベースを作って育てています。ファイル属性である日付を扱う際のコマンドについて。
はじめに
この投稿は以前「実作編ver.3」でした。内容はファイルそのものと仕組みに関する7ページに及ぶ長い記事でしたが、実作編シリーズが一旦終わってリセットされたので内容のほとんどが無意味となり、大部分を削除して一部のみ記録として残しました。
現在この投稿は「FileMakerメディア管理の作り方 R10 インポートLEVEL3 日付」に関連する投稿という位置づけになります。
尚、削除した大部分は、後の「作り方」シリーズのどこかに含まれます。
インポート手順
FileMakerで画像や映像のデータベースを作って育てる過程で、大きな転換点があります。ファイルの日付をインポートに含めることがそれにあたります。
FileMaker の機能ではインポートするファイルの属性である作成日や変更日を取得できません。AppleScript やコマンドラインツールの使用が必須となります。
インポートの手順は、転換前はこうでした。
FileMaker の機能で仮のインポート -> 本番のインポート -> メインテーブルへ転記
これを次のように変更します。
外部コマンドでインポートするリストを作成 -> FileMakerのインポート -> メインテーブルへ転記
ここまで変えなくても、途中でファイル作成日取得を挟み込めばいいじゃん。と、最初は思ったのですが実際にやってみると二度手間になるだけで、それなら最初からそれを基準にすれば良いと判断しました。
ということでインポート作業の最初からAppleSccriptとコマンドラインを使用する仕組みとなりました。AppleScript からコマンドを走らせたり、それをFileMakerで簡単制御することについてはここでは省略します。以下を参照してください。
Macで実行可能なFileMakerコード管理 CodeManager
AppleScriptからコマンドを送り込む三つの方法 スキル別まとめ
日付ゲットのコードについて
最初にAppleScriptについて書いています。現在、使用していないコマンドですが備忘録として残しておこうと思いまして。というのも、ここに自分で書いていることをすっかり忘れていて「へえ」と思いながら読み返したからです。
AppleScript
日付をゲットするAppleScriptのスクリプトはシンプルで、ファイル属性からGetで日付を引っ張ってくるだけです。
作成日なら get creation date of file パス 、
変更日なら get modification date of file パス です。
個別に引っ張ってくるだけなら簡単ですが、希望としては「パス+作成日+変更日」の形で情報を頂きたいんです。出力フォーマットを好きに作れるでしょうか。作れます。
変数にテキストとして詰め込みます。
パスを thePath、作成日を cDate 変更日を mDate と、カッコいい名前の変数に仕込み、最後に theList というカッコいい名前の変数を使って中に詰め込みます。
set theList to "" & thePath & "+++" & "+++" & cdate & "+++" & mdate
“+++” はセパレータのつもりです。あとでFileMakerで”+++”を改行に置換するんです。最初に “” があるのは、最初がパスだと文字列じゃない受け取り方をされてしまうようなので、まず空の文字を置いてそれに繋げる形にしました。
もう一つ希望があります。
ターミナルコマンドで pbcopy を知ってから世界が広がりました。AppleScript にも同じのありますか。あるみたいです。こうです。
set the clipboard to theList
これで変数 theList がクリップボードに入ります。FileMakerのフィールドにペーストして加工して各フィールドに振り分けます。
まとめるとこうなります。
set thePath to POSIX file "$POSIX" tell application "Finder" set cDate to get creation date of file thePath set mDate to get modification date of file thePath set theList to "" & thePath & "+++" & cDate & "+++" & mDate set the clipboard to theList end tell
これを「AppleScriptを実行」させるとあっという間に日付情報ゲット成功。
受信した電波もとい受信したデータは「パス+++作成日+++変更日」となっていますから、+++ を改行に置き換えて「1行目がパス、2行目が作成日、3行目が変更日」ということで、日付フィールドに2行目、3行目を転記します。
AppleScriptが持ってくる日付を整形
ただしそのままではいけません。日付がフォーマットされてしまってるんです。2021年9月2日 木曜日 みたいになってます。これをFMのタイムスタンプに変換します。この変換の計算式がちょっと面倒です。
最終的には不採用
このAppleScriptのスクリプト、最終的には不採用にしました。ファイル単独の操作ならこのまま行けますが、フォルダ内のファイルリストに対して同じ処理を行おうとするとき、リストを作ることそのものも大変だし、ループの処理も難しくて「どっちもイケるターミナルコマンドを使ったほうが良い」と判りました。
ターミナルコマンド
ターミナルコマンドで日付をゲットする方法はいろいろあります。フォルダ内のアイテム一括とか、フォルダ内のフォルダも含めてすべて網羅とか、やりたい事柄は複雑です。
ls
最初はリストを作るlsに期待しました。フォルダ内のファイルのみ、フォルダ内のフォルダも含む、いろいろなリストの作り方が柔軟にできそうだったからです。
でも出力フォーマットをカスタムする方法が判らなかった。さらに、作成日と変更日を両方取得することもできなかった。ウンザリするほどいろいろ試した結果、lsを却下しました。
stat
stat については stat で日付をゲット – ステイタスコマンド にすでに書きました。
ファイル属性の情報を取得するにはこいつが最適っぽいです。出力も自由自在。先ほどの AppleScript と同じように出力の書式も好きにカスタムできます。
statでは日付もフォーマットできます。でも好きな形にフォーマットできませんでした。なので UNIX タイムスタンプのままゲットしたほうが後で都合がいいです。フォーマットされてしまったものをFileMakerのタイムスタンプに変換するは困難ですが、生の数字をFMタイムスタンプに変換することは容易です。変換する計算式はいろんな賢人さまたちがネットに上げていらっしゃいます。ここでも、後ほどどこかに書きました。
話戻って、しかしstatはリスト機能がないので、フォルダ内のアイテムをどのように取得したいかによっていきなり複雑化してきます。
lsでリストを作ってそれをstatで処理するという二段構えも考えましたが、複雑さに拍車がかかるだけで手に負えませんでした。
この時点で、あれこれ複数コードを作りまくり試行錯誤を100万回繰り返し、そしてどれも面倒が過ぎてやさぐれて放棄しました。
「もう駄目だ」と矢吹ジョーのようにリングでうなだれます。「フォルダ内フォルダを選択に含めるとか、もうそういうの一切禁止にしようか」とすら思い始めました。
find
そんな中ぴかりと光が差し、天の一角がめくれて神様が顔を出し「findでやればええよ」と教えてくれました。
ループにループを重ねる複合ループでサブフォルダを探っていく地獄に陥っていた作者は、ここで初めて find についてちょっと調べて、その結果最も理想に近い挙動がそこにあることを知ります。
パスを指定して find して「ファイル限定」と指定すれば望みのファイルリストが返って来るではありませんか。サブフォルダを含む含まないも簡単に切り替えられて、あっという間に目的のリストが作成されます。最高。
find リファレンス
使用するオプションは次の通りです。
-type f ファイルのみリストします。
-not -name “.*” こう書くと不可視ファイルを除外できます。
-maxdepth 1 階層を1個のみに限定。サブフォルダを含まない場合に追加します。
find と stat を繋げた最強コード
find で見つけたファイルに対してコマンドを実行できます。これがカッコいいところです。find に stat を実行してもらいましょう。-exec と書いてその後ろにコマンドを書きます。
find $POSIX -type f -not -name ".*" -exec stat -f "%N+++%B+++%m" {} +
-exec の後ろのコマンドは stat -f “%N+++%B+++%m” です。 statで「パス+++作成日+++変更日」のフォーマットを返してくれるよう指令しています。
コマンドの後ろに謎の {} + がありますが、必要な措置だそうです。ファイルを一つずつ処理するときは {} ; 、まとめて処理するときは {} + と書くとか。まとめて処理すると高速なので、送り先コマンドが対応している場合にはこっちを書きます。
このコマンドにさらに「 | 」で pbcopy を追加します。
find $POSIX -type f -not -name ".*" -exec stat -f "%N+++%B+++%m" {} + | pbcopy
find $POSIX -type f -maxdepth 1 -not -name ".*" -exec stat -f "%N+++%B+++%m" {} + | pbcopy
これで思いっきり希望通りの結果が得られました。即ち、$POSIXにフォルダパスを代入するとフォルダ以下の全ファイルが「パス+++作成日+++変更日」のリストとなって返ってきます。下段は階層を指定したフォルダに限定します。
リストがあまりにも膨大なときは、| pbcopy ではなくファイルに書き出すのがいいかもしれません。でもまあ、クリップボードでもそこそこ大丈夫なので気に入ってこっちを使っています。