コマンドやスクリプトなど、コードを管理して実行もできる CodeManager.fmp12 の利用と仕組み その2。コマンドライン命令文を do shell script に変換する計算式について。
前の記事 Macで実行可能なFileMakerコード管理 CodeManager の続きです。
コマンドラインを do shell script に変換
フィールド CodeDoScript が本ファイルの要のひとつ、コードを実行できる形に変換する計算フィールドです。変換テンプレートを使って CodeTemp に書かれたコードを do shell script に変換します。
変換テンプレートはこのような簡単な一文です。
do shell script "$COMMAND"
“$COMMAND” に codeTemp の内容を入れ込みます。
CodeDoScript フィールドの計算式
$COMMAND を置き換える計算式で以下ですが。現状、このようになっています。ざっくり載せます。
// CodeTemp を do shell script に変換する Let ( [ code = CodeRun::codeTemp ; // テンプレートを選択 template = CodeRun::Template_DoShellScript ; // パスワード password = CodeRun::password ; // 外部ツールのパスを加える(exiftool と ffmpeg) comPath = If ( LeftWords ( code ; 1 ) = "exiftool" ; CodeRun::ExifToolの場所 ; If ( LeftWords ( code ; 1 ) = "ffmpeg" ; CodeRun::ffmpegの場所 ) ) ; // pbcopy にLANGを追加する code = Substitute ( code ; "pbcopy" ; "LANG=ja_JP.UTF-8 pbcopy" ) ; // コマンドに sudo があるとき、パスワードを含める(セキュリティがばがばにつき注意) code = If ( PatternCount ( code ; "sudo " ); Substitute ( code ; "sudo " ; "echo '" & password & "' | sudo -S " ) ; code ); // ダブルクォーテーションがあればシングルに変更 code = Substitute ( code ; "\"" ; "'" ) ; // パスを囲む(POSIX クォーテーション付け忘れがたまにあるのでその補正) code = If ( PatternCount ( code ; " $POSIX1 " ) ; Substitute ( code ; [ "$POSIX1" ; "'$POSIX1'" ] ) ; code ) ; code = If ( PatternCount ( code ; " $POSIX2 " ) ; Substitute ( code ; [ "$POSIX2" ; "'$POSIX2'" ] ) ; code ) ; code = If ( PatternCount ( code ; " $POSIX1" ) ; Substitute ( code ; [ "$POSIX1" ; "'$POSIX1'" ] ) ; code ) ; code = If ( PatternCount ( code ; " $POSIX2" ) ; Substitute ( code ; [ "$POSIX2" ; "'$POSIX2'" ] ) ; code ) ; // 複数行の処理 code = If ( PatternCount ( code ; ¶ ); Substitute ( code ; ¶ ; ";" ) ; code ) ; code = If ( Right ( code ; 2 )=" ;" ; Left (code ; Length ( code ) -2 ) ; code ); // シングルクォーテーションが重なっていれば修正する code = Substitute ( code ; "''" ; "'" ) ; // 1行スクリプトのバックグラウンド処理(オマケ的。不要なら削る) code = If ( ValueCount (CodeRun::codeTemp) = 1 and Right ( code ; 1 )≠ "&" ; code & " &" ; code ); // 最終。commandを置換 code = Substitute ( template ; "$COMMAND" ; comPath & code ); // さらに最終。category が command の場合のみ採用(それ以外は空) code = If (CodeRun::Category = "Command" ; code ) ]; code )
この計算式には、ここ DigitalBoo の挑戦の歴史と知見が込められていまして、同時に素人臭さにも満ちております。
ざっくり、何をしているのかということだけ書いていきます。Let関数使ってますので、順を追いますね。
テンプレートの選択
テンプレートを選択します。以前、複数のテンプレートがあった頃の名残ですが。
template = CodeRun::Template_DoShellScript ;
Macのパスワード
「sudo」のコマンドも実行させています。ターミナルでやるとMacのパスワードを訊かれます。これをなんと「password」というグローバルフィールドを利用して自動で送ってしまおうというセキュリティ感覚0の仕組みです。
password = password ;
ここでパスワードフィールドの内容を変数に保存して、のちほど「コマンドにsudoが含まれていれば」パスワードを自動で送り込みます。
パスワードをエコーしてパイプで sudo -S に繋げるということらしいのでそれでいきます。
code = If ( PatternCount ( code ; "sudo " ); Substitute ( code ; "sudo " ; "echo '" & password & "' | sudo -S " ) ; code );
良い子は真似してはいけませんが私は平気です。
… と思っていたらパスワードを使用せず sudo する書き方があるんですか。それをまだ知りませんので、今後の課題といたします。
次はいくつかの例外的措置です。
外部コマンドのパス
さて、ターミナルは賢いのでいきなりコマンドを書くことができますが、ターミナルをバイパスするとそうはいきません。自分でインストールしたツールを使用する場合はパスとセットで書く必要があります。以前、ExifTool が Automator で動作せずにドハマりしました。
// 外部ツールのパスを加える(exiftool と ffmpeg) comPath = If ( LeftWords ( code ; 1 ) = "exiftool" ; CodeRun::ExifToolの場所 ; If ( LeftWords ( code ; 1 ) = "ffmpeg" ; CodeRun::ffmpegの場所 ) ) ;
自分が使用する外部ツールだけを名指しで処理、すなわち、ExifToolとffmpeg の場合、コマンドの前に “/usr/local/bin/” を加えています。
個別具体的な対処の措置であり、汎用性のまったくない計算式です。他のツールを使っている方は自分用に書き加えます。
pbcopy に LANG を追加する
めちゃ使いまくる pbcopy です。このコマンド、ターミナルで使うと賢いのですがターミナルじゃないところで使うとアホになります。 ターミナルでは「pbcopy」と書きますが、do shell script では「LANG=ja_JP.UTF-8 pbcopy」と書かねばまともな動作が出来ません。
code = If ( template = template_shell ; Substitute ( code ; "pbcopy" ; "LANG=ja_JP.UTF-8 pbcopy" ) ; "pbcopy" ) ;
このように、コマンド独自ルールを発見した場合には個別に計算式に追加していく必要があります。
ものを知らないので、今のところ挙動の違いを確認して解決できているのは pbcopy のみです。他にも同じようなのを発見すれば追加します。
最後にテンプレートの $COMMAND を置き換える
そんなこんなでコードが変換できたので、変換テンプレートの $COMMAND のところに置換でぶっ込みます。
code = Substitute ( template ; "$COMMAND" ; comPath & code );
以上で、コードを変換できましたが、Let関数の最後、ここでカテゴリーに応じて生かすか殺すかを決めます。カテゴリーが command であれば採用、そうでなければ空にしておきます。元々書かれたコードがAppleScriptやメモの場合は結果が空になります。
それを一番最初にやれよ。という声が今聞こえました。その通りですね。
/* category が command の場合のみ採用(それ以外は空) */ code = If (CodeRun::Category = "Command" ; code )
コマンドラインを do shell script に変換する CodeDoScript フィールドの計算式でした。
次は、実行するスクリプトについて です。
使い方・マニュアルはこちら