# [メタ情報] # 識別子: 公開用スクリプトを生成する # 補足: 一括処理のものだけに統一した env終了 # [/メタ情報] 要約: このワークフローは、開発用の`_exe.txt`ファイルを公開用の`_pub.txt`ファイルに変換・生成するAppleScriptと、それに連携し公開物をDropboxへ同期するShellスクリプトから構成されます。 AppleScriptは、選択された`_exe.txt`ファイルを読み込み、環境設定ファイル(.env)から保存先や公開URLを動的に取得します。ファイル内のメタ情報については、「状態: 公開用」への設定や更新日時の削除など調整を行い、Google/DropboxのID、ローカルパス、特定の文字列(例:XXXXXX)といった機密情報を匿名化・一般化するサニタイズ処理を実行します。さらに、`key_patterns.txt`に基づく秘密キー置換も行われます。生成された`_pub.txt`ファイルは指定の公開用ディレクトリに保存され、その直リンクURLはクリップボードにコピーされます。 処理後、AppleScriptはDropbox同期用のShellスクリプトを自動的にバックグラウンドで起動します。このShellスクリプトは、設定された公開用ディレクトリ(`scripts_pub`)の内容を、`rsync`コマンドを用いてDropbox内の指定されたパスに自動同期し、公開用ファイルの一貫性を保ちます。これにより、開発中のスクリプトを安全かつ効率的に公開し、共有するプロセスが自動化されます。 公開用スクリプトを生成する_一括.workflow ``` on run {input, parameters} -- ===== 1. 環境設定(金庫 .env からの動的ロード & 環境差の自動解決) ===== set currentUser to short user name of (system info) set envPath to "/Users/" & currentUser & "/python_scripts/.env" -- (A) 公開用生成物の保存先を金庫から動的取得 set FACTORY_SAVE_DIR to "" try set FACTORY_SAVE_DIR to do shell script "grep 'FACTORY_SAVE_DIR' " & quoted form of envPath & " | sed -E 's/^FACTORY_SAVE_DIR=//' | sed -E 's/^[\\\"\\x27]//;s/[\\\"\\x27]$//'" end try -- 金庫に無い場合は従来の稼働実績パスに自動フォールバック(現状維持) if FACTORY_SAVE_DIR is "" then if currentUser is "XXXXXX" then set FACTORY_SAVE_DIR to "<任意のフォルダパス>" else set FACTORY_SAVE_DIR to "<任意のフォルダパス>" end if end if -- (B) 自分用生成物の保存先を金庫から動的取得 set MY_EXE_DIR to "" try set MY_EXE_DIR to do shell script "grep 'MY_EXE_DIR' " & quoted form of envPath & " | sed -E 's/^MY_EXE_DIR=//' | sed -E 's/^[\\\"\\x27]//;s/[\\\"\\x27]$//'" end try if MY_EXE_DIR is "" then if currentUser is "XXXXXX" then set MY_EXE_DIR to "<任意のフォルダパス>" else set MY_EXE_DIR to "<任意のフォルダパス>" end if end if -- (C) Xserver 側での公開ベースURLを金庫から動的取得 set SITE_BASE to "" try set SITE_BASE to do shell script "grep 'SITE_BASE_URL' " & quoted form of envPath & " | sed -E 's/^SITE_BASE_URL=//' | sed -E 's/^[\\\"\\x27]//;s/[\\\"\\x27]$//'" end try if SITE_BASE is "" then set SITE_BASE to "https://XXXXXX.com/wp-content/pmedia/" end if -- 保存先フォルダを必ず作成 try do shell script "/bin/mkdir -p " & quoted form of FACTORY_SAVE_DIR do shell script "/bin/mkdir -p " & quoted form of MY_EXE_DIR on error errm display alert "保存先フォルダエラー" message "フォルダを作成できませんでした。" & return & errm return end try if input is {} then display alert "ファイル未選択" message "Finderで *_exe.txt または *_wip.txt を選んで実行してください。" return end if set outFolder to FACTORY_SAVE_DIR if outFolder does not end with "/" then set outFolder to outFolder & "/" set exeFolder to MY_EXE_DIR if exeFolder does not end with "/" then set exeFolder to exeFolder & "/" set processedExe to 0 set processedPub to 0 set urlBlocks to {} repeat with selAlias in input try set srcPath to POSIX path of selAlias set qsrc to quoted form of srcPath set baseName to do shell script "/usr/bin/basename " & qsrc -- *_exe.txt または *_wip.txt か判定 set isTarget to do shell script "/bin/echo " & qsrc & " | /usr/bin/tr -d '\\r' | /usr/bin/sed -E 's/[[:space:]]+$//' | /usr/bin/grep -Eiq '(_exe\\.txt$|_wip\\.txt$)' && echo YES || echo NO" -- ★ 変更箇所:「空_exe.txt」および「空_wip.txt」を除外 ★ if isTarget is "YES" and baseName is not "空_exe.txt" and baseName is not "空_wip.txt" then -- ★ 1. 自分用(scripts_exe)へのコピー ★ set destExePath to exeFolder & baseName do shell script "/bin/cp -f " & qsrc & " " & quoted form of destExePath set processedExe to processedExe + 1 -- ★ 2. 公開用(scripts_pub)の生成(_exe.txt のみ対象) ★ set isExe to do shell script "/bin/echo " & qsrc & " | /usr/bin/tr -d '\\r' | /usr/bin/sed -E 's/[[:space:]]+$//' | /usr/bin/grep -Eiq '_exe\\.txt$' && echo YES || echo NO" if isExe is "YES" then set pubNameRaw to do shell script "/bin/echo " & quoted form of baseName & " | /usr/bin/sed -E 's/_exe\\.txt$/_pub\\.txt/I'" set pubName to do shell script "/usr/bin/python3 -c 'import sys,unicodedata;print(unicodedata.normalize(\"NFC\",sys.argv[1]))' " & quoted form of pubNameRaw set destPath to outFolder & pubName set qdst to quoted form of destPath -- 先頭が [メタ情報] かチェック set hasMeta to do shell script "head -1 " & qsrc & " | /usr/bin/grep -q '^# \\[メタ情報\\]' && echo YES || echo NO" if hasMeta is "NO" then set ident to do shell script "/bin/echo " & quoted form of baseName & " | /usr/bin/sed -E 's/\\.txt$//I'" set metaHeader to "# [メタ情報]" & return & ¬ "# 識別子: " & ident & return & ¬ "# 補足: " & return & ¬ "# [/メタ情報]" & return & return set tmpMeta to do shell script "/usr/bin/mktemp -t metahead" do shell script "/usr/bin/printf %s " & quoted form of metaHeader & " > " & quoted form of tmpMeta set tmpWorkExe to do shell script "/usr/bin/mktemp -t exework" do shell script "/bin/cat " & quoted form of tmpMeta & " " & qsrc & " > " & quoted form of tmpWorkExe do shell script "/bin/mv " & quoted form of tmpWorkExe & " " & qsrc do shell script "/bin/rm -f " & quoted form of tmpMeta else set tmpWorkExe2 to do shell script "/usr/bin/mktemp -t exework" do shell script "/usr/bin/awk 'BEGIN{inm=0} /^# \\[メタ情報\\]/{inm=1} inm && /^# *更新日時:/{next} {print} /^# \\[\\/メタ情報\\]/{inm=0}' " & qsrc & " > " & quoted form of tmpWorkExe2 do shell script "/bin/mv " & tmpWorkExe2 & " " & qsrc end if set tmpMetaPub to do shell script "/usr/bin/mktemp -t metapub" -- ★【ゆらぎ超柔軟解決】「# 状態:」の半角コロン、全角コロン、スペース混入揺れを完璧に包囲する超柔軟awkフィルタ do shell script "/usr/bin/awk 'BEGIN{inm=0} /^# \\[メタ情報\\]/{inm=1} inm{ if($0 ~ /^# *状態 *[::]/){print \"# 状態: 公開用\"} else if($0 ~ /^# *更新日時:/){next} else {print} } /^# \\[\\/メタ情報\\]/{exit}' " & qsrc & " > " & quoted form of tmpMetaPub set tmpBody to do shell script "/usr/bin/mktemp -t bodyraw" do shell script "/usr/bin/sed '1,/^# \\[\\/メタ情報\\]$/d' " & qsrc & " > " & quoted form of tmpBody set tmpBodySan to do shell script "/usr/bin/mktemp -t bodysan" set sedRules to "/usr/bin/sed -E " & ¬ " -e 's#ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789#ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789#g' " & ¬ " -e 's#(https?://docs\\.google\\.com/(spreadsheets|document|presentation)/d/)[^/]+#\\1<各GoogleファイルのID>#g' " & ¬ " -e 's#(https?://drive\\.google\\.com/file/d/)[^/]+#\\1#g' " & ¬ " -e 's#(https?://www\\.dropbox\\.com/scl/fi/)[A-Za-z0-9_-]+#\\1#g' " & ¬ " -e 's#(https?://www\\.dropbox\\.com/s/)[A-Za-z0-9_-]+#\\1#g' " & ¬ " -e 's#([?&]rlkey=)[A-Za-z0-9_-]+#\\1#g' " & ¬ " -e 's#([A-Za-z0-9_]*KEY\\s*=\\s*[\"])[^\"]+([\"])#\\1<各APIキー>\\2#g' " & ¬ " -e 's#([A-Za-z0-9_]*SECRET\\s*=\\s*[\"])[^\"]+([\"])#\\1<各シークレット値>\\2#g' " & ¬ " -e 's#([A-Za-z0-9_]*TOKEN\\s*=\\s*[\"])[^\"]*([\"])#\\1<各トークン値>\\2#g' " & ¬ " -e 's#([A-Za-z0-9_]*SPREADSHEET_ID\\s*=\\s*[\"])[^\"]+([\"])#\\1<スプレッドシートID>\\2#g' " & ¬ " -e 's#([A-Za-z0-9_]*DOC_ID_+\\s*=\\s*[\"])[^\"]+([\"])#\\1<ドキュメントID>\\2#g' " & ¬ " -e 's#([A-Za-z0-9_]*SHEET_ID\\s*=\\s*[\"])[^\"]+([\"])#\\1<シートID>\\2#g' " & ¬ " -e 's#([A-Za-z0-9_]*_F*_ID\\s*=\\s*[\"])[^\"]+([\"])#\\1<連携用ID>\\2#g' " & ¬ " -e 's#(PUSH_META_LIB_JSON_ID\\s*=\\s*[\"])[^\"]+([\"])#\\1\\2#g' " & ¬ " -e 's#([A-Za-z0-9_]*SA_JSON[A-Za-z0-9_]*\\s*=\\s*[\"])[^\"]+([\"])#\\1<サービスアカウントJSONのパス>\\2#g' " & ¬ " -e 's#(GOOGLE_APPLICATION_CREDENTIALS\\s*=\\s*[\"])[^\"]+([\"])#\\1<認証情報JSONのパス>\\2#g' " & ¬ " -e 's#(XXXXXX_BLOG_DRIVE_PATH\\s*=\\s*[\"])[^\"]+([\"])#\\1<ご自身のドライブパス>\\2#g' " & ¬ " -e 's#(GAS_URL\\s*=\\s*[\"])[^\"]+([\"])#\\1<公開したGASのURL>\\2#g' " & ¬ " -e 's#(VIMEO_EMBED_JSON_ENDPOINT\\s*=\\s*[\"])[^\"]+([\"])#\\1<エンドポイントURL>\\2#g' " & ¬ " -e 's#(MY_SCREEN_SHARING_PASSCODE\\s*=\\s*[\"])[^\"]+([\"])#\\1<設定したパスコード>\\2#g' " & ¬ " -e 's#(token=)[A-Za-z0-9_-]+#\\1<個別のトークン文字列>#g' " & ¬ " -e 's#bbbbbbbb\\.yyyyyyyy@gmail\\.com#<ご自身のメールアドレス>#g' " & ¬ " -e 's#(/Users/|/Volumes/|/home/)[^[:space:]\"]*[iI][mM][aA][kK][aA][tT][^[:space:]\"]*/([^/[:space:]\"]+\\.[a-zA-Z0-9_-]+)#<任意のフォルダパス>/\\2#g' " & ¬ " -e 's#(/Users/|/Volumes/|/home/)[^[:space:]\"]*[iI][mM][aA][kK][aA][tT][^[:space:]\"]*#<任意のフォルダパス>#g' " & ¬ " -e 's#\\\"([A-Za-z0-9_-]{28,})\\\"#\\\"<固有のランダム文字列>\\\"#g' " & ¬ " -e 's#'\\''([A-Za-z0-9_-]{28,})'\\''#'\\''<固有のランダム文字列>'\\''#g' " & ¬ " -e 's#ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789#ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789#g' " do shell script sedRules & quoted form of tmpBody & " > " & quoted form of tmpBodySan do shell script "/bin/cat " & quoted form of tmpMetaPub & " " & quoted form of tmpBodySan & " > " & qdst & " && /bin/rm -f " & quoted form of tmpMetaPub & " " & quoted form of tmpBody & " " & quoted form of tmpBodySan set tmpWorkPub1 to do shell script "/usr/bin/mktemp -t pubwork" do shell script "/usr/bin/sed -E 's#[iI][mM][aA][kK][aA][tT][mM]1#XXXXXX#g; s#[iI][mM][aA][kK][aA][tT]#XXXXXX#g' " & qdst & " > " & quoted form of tmpWorkPub1 do shell script "/bin/mv " & quoted form of tmpWorkPub1 & " " & qdst set pubDir to do shell script "dirname " & qdst set keyFile to pubDir & "/key_patterns.txt" set keyFileExists to do shell script "[ -f " & quoted form of keyFile & " ] && echo YES || echo NO" if keyFileExists is "YES" then set rawKeys to do shell script "/usr/bin/grep -a -E '^[[:space:]]*[^#[:space:]][^#]*$' " & quoted form of keyFile & " | /usr/bin/grep -a -v ',' | /usr/bin/sed -E 's/[[:space:]]+#.*$//; s/^[[:space:]]+//; s/[[:space:]]+$//'" if rawKeys is not "" then set keyList to paragraphs of rawKeys repeat with k in keyList set keyName to contents of k if keyName is not "" then set escName to do shell script "/usr/bin/python3 -c " & quoted form of "import sys,re;print(re.escape(sys.argv[1]))" & " " & quoted form of keyName set sedExpr to "s#[[:<:]]" & escName & "[[:>:]][[:space:]]*=[[:space:]]*[\\\"\\'][^\\\"\\']*[\\\"\\']#" & keyName & " = \\\"<" & keyName & ">\\\"#g" set tmpWorkPub2 to do shell script "/usr/bin/mktemp -t pubwork" do shell script "/usr/bin/sed -E -e " & quoted form of sedExpr & " " & qdst & " > " & quoted form of tmpWorkPub2 do shell script "/bin/mv " & tmpWorkPub2 & " " & qdst end if end repeat end if set rawPairs to do shell script "/usr/bin/grep -a ',' " & quoted form of keyFile & " | /usr/bin/sed -E 's/[[:space:]]+#.*$//; s/^[[:space:]]+//; s/[[:space:]]+$//'" if rawPairs is not "" then set pairList to paragraphs of rawPairs repeat with p in pairList set t to contents of p if t is not "" then set tidx to offset of "," in t if tidx > 0 then set origVal to text 1 thru (tidx - 1) of t set replVal to text (tidx + 1) thru -1 of t set tmpWorkPub3 to do shell script "/usr/bin/mktemp -t pubwork" do shell script "/usr/bin/perl -0777 -pe 'BEGIN{$o=shift;$r=shift;} s/\\Q$o\\E/$r/g' -- " & quoted form of origVal & " " & quoted form of replVal & " " & qdst & " > " & quoted form of tmpWorkPub3 do shell script "/bin/mv " & tmpWorkPub3 & " " & qdst end if end if end repeat end if end if set relPathNFC to "scripts_pub/" & pubName set urlPlain to SITE_BASE & relPathNFC copy urlPlain to end of urlBlocks set processedPub to processedPub + 1 end if else display notification "対象外です: " & srcPath with title "スキップ" end if on error errm display notification errm with title "生成エラー" end try end repeat if processedExe > 0 then if (count of urlBlocks) > 0 then set my text item delimiters to return set fullUrlText to urlBlocks as text set my text item delimiters to "" set the clipboard to fullUrlText if processedPub > 15 then set my text item delimiters to return set displayUrlText to (items 1 thru 15 of urlBlocks as text) & return & "(...他 " & (processedPub - 15) & " 件)" set my text item delimiters to "" else set displayUrlText to fullUrlText end if display dialog ("完了:" & return & "自分用 (" & processedExe & "件) を scripts_exe に生成" & return & "公開用 (" & processedPub & "件) を scripts_pub に生成" & return & return & displayUrlText & return & return & "※直リンクURLをクリップボードにコピーしました") buttons {"OK"} default button "OK" with icon note else display dialog ("完了:" & return & "自分用 (" & processedExe & "件) を scripts_exe に生成" & return & "※公開用の生成はありませんでした。") buttons {"OK"} default button "OK" with icon note end if else display alert "対象なし" message "選択の中に有効な *_exe.txt または *_wip.txt が見つかりませんでした。" end if end run ``` <任意のフォルダパス>/sync_scripts_pub_to_dropbox.sh ``` #!/bin/bash set -x export PATH="/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin" # ===== 1. 金庫(.env)のロードとMeister 1 / 2 の環境差を自動吸収 ===== if [ -f "$HOME/python_scripts/.env" ]; then export $(grep -v '^#' "$HOME/python_scripts/.env" | xargs) fi # Homebrew の rsync パスを動的に特定 if [ -x /opt/homebrew/bin/rsync ]; then RSYNC="/opt/homebrew/bin/rsync" else RSYNC="/usr/bin/rsync" fi # 同期元(金庫に指定があればそちらを優先、なければデフォルトにフォールバック) if [ -z "${SCRIPTS_PUB_SRC}" ]; then if [ "$(whoami)" = "XXXXXX" ]; then SRC="<任意のフォルダパス>" else SRC="<任意のフォルダパス>" fi else SRC="${SCRIPTS_PUB_SRC}" fi # 同期先(金庫に指定があればそちらを優先、なければデフォルトにフォールバック) DST="${SCRIPTS_PUB_SYNC_DST:-/Volumes/NO3_SSD/mybox/mybox_1/pmedia/scripts_pub}" mkdir -p "$DST" sleep 8 "$RSYNC" -av --delete --iconv=utf-8,utf-8-mac "$SRC/" "$DST/" exit 0 ```