読者です 読者をやめる 読者になる 読者になる

ごんれのラボ

iOS、Android、Adobe系ソフトの自動化スクリプトのことを書き連ねています。

Illustratorを開かずに配置ファイルを収集する 続編

[Illustrator][AppleScript][Ruby]Illustratorを開かずに配置ファイルを収集するの続編です。

 

2017/2/18追記

下記の環境で動作確認しました。

  • OS X El Capitan(10.11.6)
  • CC 2015.3

 

本編

上記エントリで公開したAppleScriptは結構たくさんの方から評価をしてもらっているようです。

Twitterなり勉強会なりで「使ってます!」「助かってます!」というお言葉も頂戴しており、嬉しい限りです。

ただ、いろいろな不具合も起きてしまっているようで、「早く修正してー」と言われてしまうこともしばしばありました。

直そう直そうと思ってはいたものの、仕事やレノくんもふもふするのが忙しくて延び延びになってしまっていました。

フィードバックしていただいた方々、申し訳ないです。

 

ということで、今日頑張って修正しました!

Rubyのコードを大幅に書き換えて、AppleScriptのほうもいろいろリファクタリングしました。

この数ヶ月、暇を見つけては会社でいろんなスクリプト(Ruby含む)を書きまくっていたので、その辺の経験と知識を反映したつもりです。

 

修正した箇所は

●バージョン判別をRuby内で行うように修正(Adobe Illustrator CS2という文字があるかどうか)

●XMPだけを取得するように修正

●XMPのフルパスが存在しないときは次にIllustratorの同階層の画像を複製できるか試すように修正

●Windows環境で作成されたファイルの配置画像収集も可能なように修正

●同じような処理を行うサブルーチンを一つに統合した

●AppleScriptにRubyをバンドルさせるのをやめた

 

まず重いIllustratorファイル対応のためXMPだけを変数に代入して、その中で文字列操作することにしました。

ただしXMPの終了タグを検知して例外を発生させているためCS2以降のファイルでしか効果はでません。

次に不安定だったAppleScriptでのIllustratorのバージョン判定をやめて、Rubyで処理することにしました。

判定方法はXMPの中に「Adobe Illustrator CS2」という文字があったら例外を発生させて処理を中止するというものです。

バージョンダウンしたファイルだとうまく動かないかもしれませんが、バージョンダウンしないよね?

次にXMPから取得したフルパスが存在しないときはIllustratorファイルと同階層にあるファイルを複製するようにして、それでも見つからないものだけエラーログに書き出すようにしました。

次にざっくりとではありますがWindows環境で作成されたIllustratorファイルからも配置画像を複製できるようにしました。

Windowsのフルパスの中にバックスラッシュが入っていることを利用しているのでWindowsのバージョンや環境によってはうまく動かないと思います。

おまけ程度の機能追加だと思ってもらえれば。

次にサブルーチンを整理しました。

最後にRubyのバンドルをやめました。

ついでにAppleScriptの名前も変えました。

 

今回の修正でだいぶ完成に近づいたと思います。

不具合などあればコメントなどでお知らせください。

ご自分で直せるのであれば、どこを直したか教えていただけるとうれしいです。

 

以下のコードでは10.9には対応できていません、。

更新が面倒になったのでコードを読みたい方はダウンロードして読んでください。

 

Ruby

#! ruby -Ku
require 'CGI'
require 'kconv'

temp = ""
linkFilePath = "" ; #リンクファイルのパスの入れ物

#XMP情報を抽出して変数に代入
def xmpRead(fileObj, temp)
    begin
        while line = fileObj.gets
            line = CGI.unescapeHTML(line)#HTMLエスケープされてるのでアンエスケープ
            line = line.toutf8
            
            #XMP終了時に例外を発生させる
            if /^<\/x:xmpmeta>/ =~ line then
                raise "loop stop" #raiseで例外を発生できる
            end
            
            if temp == ""
                temp = line
                else
                temp = temp + line
            end
        end
        rescue
        return temp #tempを返す
    end
end

def illustratorPackage(temp, linkFilePath)
    if /Adobe Illustrator CS2/ =~ temp
        raise "before CS2"
    end
    
    linkFilePath = temp.scan(/^\s+?(.+?)<\/stRef:filePath>/)
    
    if linkFilePath == []
        linkFilePath = "nil"
    end
    return linkFilePath #linkFilePathを返す
    rescue
end

temp = xmpRead(ARGF, temp)
result = illustratorPackage(temp, linkFilePath)
puts result

 

AppleScript

on open thisList
    tell application "Finder"

        --Rubyのバージョンチェック
        if exists ((home as text) & ".bash_profile") then
            set ruby_version to do shell script "source ~/.bash_profile; ruby -e 'print \"ERROR\" if RUBY_VERSION <= \"1.8.1\"'"
        else
            set ruby_version to do shell script "ruby -e 'print \"ERROR\" if RUBY_VERSION <= \"1.8.1\"'"
        end if
        
        if ruby_version is "ERROR" then
            display dialog "このスクリプトはRubyバージョンが1.8.2以上で動作します"
            error number -128
        end if
        
        --変数初期化
        set dPath to desktop as text --デスクトップのパス取得
        set noExtractFileList to "" --エラーが出たリンクファイルのパスを入れる箱
        set textFile to dPath & "収集できなかったリンクファイル.txt" --ログ書き出し 用のテキストファイルの名前
        set errorFileLog to "" --エラーが出たファイルのパスを入れる箱
        set skipFile to 0 --CS2以下のファイルのカウント用
        
        --Rubyのファイルを取得
        set my_script_name to "IllustratorPackage.rb"
        set my_script_folder to parent of (path to me) as Unicode text
        set my_script to my_script_folder & my_script_name
        set my_script to (quoted form of POSIX path of my_script)
        
        --ここからメイン処理
        repeat with k in thisList
            set input_file to (quoted form of POSIX path of contents of k) as Unicode text --Unicode textに変換しないとダメ

            if exists ((home as text) & ".bash_profile") then
                do shell script "source ~/.bash_profile; ruby " & my_script & " " & input_file --Rubyで処理して戻り値を取得
            else
                do shell script "ruby " & my_script & " " & input_file --Rubyで処理して戻り値を取得
            end if
            
            set outputList to result --変数に代入
            
            --Rubyの戻り値がnilじゃなかったら(CS3以上でリンクファイルがあれば)
            if outputList is not "nil" then
                set linkFileList to my serchSplit(outputList, ASCII character (13)) --リストにする

                --デスクトップにフォルダを作成しリンクファイルをコピーする処理へ
                set resultList to my LinkFilePackage(linkFileList, noExtractFileList, k)
                duplicate k to item 1 of resultList --デスクトップのbackFolに複製する
                
                if (item 2 of resultList) is not "" then
                    set errorFilePath to k as string
                    set errorFile to last item of (my serchSplit(errorFilePath, ":"))
                    set errorFileLog to errorFileLog & "★" & errorFile & "で収集できなかったリンクファイル" & return & (item 2 of resultList) & return
                end if
                
                delay (0.5) --同名フォルダ作成のエラーを回避するため1秒待つ
            else if outputList is "nil" then --2012.09.24追記--リンクファイルなしも収集するように変更
                set linkFileList to my serchSplit(outputList, ASCII character (13)) --リストにする
                set resultList to my LinkFilePackage(linkFileList, noExtractFileList, k)
                duplicate k to item 1 of resultList
                delay (0.5)
            else
                set skipFile to skipFile + 1
            end if
        end repeat
        
        --エラーログの書き出し
        if errorFileLog is not "" then
            try
                set OutPutText to open for access textFile with write permission
                set eof OutPutText to 0
                write "ここに書き出されたファイルは収集できませんでした。Illsutratorデータのリンク情報が正しくない可能性があります。Illustratorデータを再保存した後、再度スクリプトを使用してください。" & return & return to OutPutText
                write errorFileLog to OutPutText
                close access OutPutText
            on error errMsg
                display dialog errMsg
                close access OutPutText
            end try
        end if
    end tell
    
    if ((count thisList) - skipFile) > 0 then
        display dialog ((count thisList) as string) & "ファイル中の" & (((count thisList) - skipFile) as string) & "ファイルを収集しました"
    else
        display dialog "収集されませんでした"
    end if
end open

--デスクトップにフォルダを作成しリンクファイルをコピーする処理
to LinkFilePackage(linkFileList, noExtractFileList, k)
    tell application "Finder"
        --バックアップファイルのコピー用にデスクトップに現在時刻名のフォルダを作成する
        set dPath to desktop as text --デスクトップのパス取得
        set folName to (do shell script "date '+%Y-%m-%d %H-%M-%S'") --現在時刻取得
        set backFol to make new folder at dPath with properties {name:folName} --デスクトップにフォルダ作成
        set label index of backFol to 2 --ラベルを付ける
        
        repeat with i from 1 to count linkFileList
            try
                set linkFilePath to (item i of linkFileList) as POSIX file --as POSIX fileで:区切りのパスに戻せる
                set linkFilePath to file linkFilePath --file 〜ってしないとダメ(ファイル参照させないとダメ)
                duplicate linkFilePath to backFol with replacing --デスクトップのbackFolに複製する(同名ファイルは上書き)
            on error --複製できなかったファイルの処理(Illustratorファイルと同階層のファイルを複製)
                --Windowsで作成されたデータもざっくり判別(パスの中に\があるかどうかで判別)
                if "\\" is in (item i of linkFileList) then
                    set errorLinkName to last item of (my serchSplit((item i of linkFileList), "\\")) --ファイル名をサブルーチンで取得
                else
                    set errorLinkName to last item of (my serchSplit(linkFilePath as Unicode text, ":")) --ファイル名をサブルーチンで取得
                end if
                
                --同一階層からリンクファイルをコピーする
                try
                    set illFileFol to (container of k) as Unicode text --illustratorファイルの内包されているフォルダを取得
                    set linkFilePath2 to file (illFileFol & errorLinkName) as Unicode text --file 〜ってしないとダメ(ファイル参照させないとダメ)
                    duplicate linkFilePath2 to backFol with replacing --デスクトップのbackFolに複製する(同名ファイルは上書き)
                on error
                    --同階層からもコピーできなければエラーログに代入する
                    set noExtractFileList to noExtractFileList & (errorLinkName as string) & return
                end try
            end try
        end repeat
        
        return {backFol, noExtractFileList} --メインルーチンにListで戻す
    end tell
end LinkFilePackage

--分割サブルーチン
to serchSplit(targetStr, splitStr)
    set str to targetStr as Unicode text
    set OriginalDelimiters to AppleScript's text item delimiters
    set AppleScript's text item delimiters to splitStr
    set itemsList to text items of str
    set AppleScript's text item delimiters to OriginalDelimiters
    
    --itemsListにリストで代入されているからあとはご自由に
    return itemsList
end serchSplit

 

 

ダウンロードはこちら。

IllustratorPackage