Thursday, September 8, 2016

#1 2012-04-03 02:33:11 am

brownaa
Member
Registered: 2010-05-30
Posts: 3

Batch convert files recursively

Hey all,

I'm not new to programming, but I am new to AppleScript.  I'd like some help debugging this script which is meant to have a folder dragged onto it to execute.  The file then recursively opens each file and saves a copy of the file as a Pages document within the same directory.

Applescript:

on open theFiles
   tell application "Pages"
       repeat with aFile in theFiles
           if aFile ends with ".cwk" then
               open aFile
               set docName to name of front document
               -- Remove .cwk extension.
               set prevTIDs to AppleScript's text item delimiters
               set AppleScript's text item delimiters to ".cwk"
               -- Add .pages extension.
               set docName to first text item of docName & ".pages"
               set AppleScript's text item delimiters to prevTIDs
               -- Get folder that dropped file exists in.
               tell application "Finder"
                   set sourceFolder to (container of aFile) as Unicode text
               end tell -- Finder
               -- Save file to folder that dropped file exists in.
               set docPathAndName to sourceFolder & docName
               save front document in docPathAndName
               close front document
           end if
       end repeat
   end tell
end open

Offline

 

#2 2012-04-03 02:57:36 am

Yvan Koenig
Member
Registered: 2006-09-14
Posts: 2418

Re: Batch convert files recursively

You are starting on wrong basis.

(1) AppleWorks file names aren't always ending with ".cwk"
(2) iWork apps aren't able to open every AppleWorks files, only those created by AppleWorks 6.x
(3) Pages isn’t able to open every AppleWorks 6 documents, only those whose kind is Word Processor.

There is no way to identify these files using only documented attributes.

(a) As written above the name extension isn’t always available.
(b) the file type and creator type properties aren’t always available
(c) under Lion, the type identifier isn't defined so we get something like "dyn.agk8ygz41na"
(d) when they are available, these attributes don't allow us to make the difference between AW6 documents and documents created with older versions.

This is was, for years, I delivered scripts relying upon undocumented attributes.

You may find them in my public BOX account :
http://www.box.com/s/00qnssoyeq2xvc22ra4k

download :
public_YK > for_iWork > batch_AWx2iWork.zip

Yvan KOENIG (VALLAURIS, France) mardi 3 avril 2012 09:57:31

Offline

 

#3 2012-04-03 08:22:05 pm

brownaa
Member
Registered: 2010-05-30
Posts: 3

Re: Batch convert files recursively

Thanks for the reply.

You need me to clarify some points so you can provide me with better feedback I think.

1) all the files end in .cwk
2) all files were created with version 6+
3) all files are word processing files

You've lost me on why I need to delve into document attributes here.

Offline

 

#4 2012-04-03 08:51:54 pm

brownaa
Member
Registered: 2010-05-30
Posts: 3

Re: Batch convert files recursively

Thanks Yvan Koenig.  I can report that I have successfully implemented your script with a slight modification.

I did not want to delete the existing file from the directory and place it in a zip file, so I have removed those steps.  It was otherwise very robust for my purposes!  Thanks!!!

Applescript:

--[SCRIPT batch_AW6_2iWork]
(*
Enregistrer ce script en tant qu'application.
Exécuter ce script ou déposer
l'icône d'un dossier sur son icône.
Il importe les tableurs et traitement de texte AppleWorks 6 du dossier dans Numbers ou Pages
et enregistre les documents Numbers ou Pages créés
dans le dossier source (respectant l'arborescence).

Les anomalies éventuelles sont répertoriées dans le fichier
"import2iWorkReport.txt" déposé sur le bureau

Activités annexes :
(1) le dossier source est préservé dans une archive zip.
(2) les fichiers de type vectoriel (CWGR) sont préservés dans un sous-dossier dont le nom est défini par la property nom_GR.
(3) les autres fichiers qui ne peuvent être traités sont préservés dans un sous-dossier dont le nom est défini par la property nom_alt.
(4) les fichiers originaux qui ont pu être exportés sont effacés.
(5) Le script ne peut hélas pas se prémunir d'un éventuel blocage durant l'importation dans Numbers ou Pages. Dans ce cas, forcer le redémarrage est la seule issue disponible.

--=====

Save the script as application.
Run it or drag and drop a folder icon on its icon.
It import AppleWorks 6 SS or WP files stored in the folder in Numbers or Pages
and save the created Numbers or Pages document
in the source folder (including original hierarchy).

Errors are reported in the file
"import2iWorkReport.txt" stored on the desktop.

Complementary tasks :
(1) the source folder is archived in a zip file.
(2) the Draw files (CWGR) are stored in a subfolder whose name is defined by the property nom_GR
(3) the other files which can't be treated are stored in a subfolder whose name is defined by the property nom_alt
(4) the original files which were exported are deleted
(5) Alas, the script can't recover cases where Numbers or Pages freeze during an import process. Reboot is the unique emergency issue available.

Yvan KOENIG (VALLAURIS, France)
2008/02/07
2008/04/28
2009/01/25
2011/10/06
2011/10/07
2011/10/09 -- we may drop file(s) or folder(s) on the script's icon
2011/10/13 -- don't treat old AW WP or SS
*)


property srcTypeId : "com.apple.appleworks.cwk"
property v6 : " [v6.0]" -- attention à l'espace de tête
property nomDuRapport : "" -- globale
property nom_GR : "" -- globale
property nom_alt : "" -- globale

property theApp : "" -- globale
property theExt : "" -- globale
property rapport : "" -- globale
property dossierDeStockage : "" -- globale

--=====

on run (* lignes exécutées si on double clique sur l'icône du script application
• lines executed if one double click the application script's icon *)

   activate
   (choose folder) as text
   my main({result})
end run

--=====

on open (sel) (* sel contient une liste d'alias des éléments qu'on a déposés sur l'icône du script (la sélection)
• sel contains a list of aliases of the items dropped on the script's icon (the selection) *)

   my main(sel)
end open

--=====

on main(les_originaux)
   local dest, p2d, p2r, MsgErr, NroErr
   my nettoie()
   
   if my parleAnglais() then
       set nomDuRapport to "report_AW2iWork.txt"
       set nom_GR to "Draw"
       set nom_alt to "Others"
       my afficheLeMessage("Don’t click when the script is running." & return & "Except, of course, if it ask for.")
   else
       set nomDuRapport to "rapport_AW2_vers_Work.txt"
       set nom_GR to "Vectoriel"
       set nom_alt to "Autres"
       my afficheLeMessage("Éviter de cliquer durant l'exécution du script" & return & "sauf s’il le demande.")
   end if
   try
       repeat with un_original in les_originaux
           set un_original to un_original as text
           if un_original ends with ":" then
               set dest to quoted form of POSIX path of ((text 1 thru -2 of un_original) & ".zip")
           else
               set dest to quoted form of POSIX path of (un_original & ".zip")
           end if
           (*
Archive the source folder in a zip file *)

           --do shell script "ditto -ck " & quoted form of POSIX path of un_original & " " & dest
           (*
Enter the main loop *)

           
           try
               my exploreTraite(un_original as alias, "")
           end try
       end repeat
       if rapport = "" then
           if my parleAnglais() then
               set rapport to "No problem during the recoding process."
           else
               set rapport to "Conversion réussie sans incident."
           end if
       end if
       (*
Create a report text file on the Desktop *)

       set p2d to path to desktop
       set p2r to "" & p2d & nomDuRapport
       tell application "System Events"
           if exists file p2r then delete file p2r
           make new file at end of p2d with properties {name:nomDuRapport}
       end tell
       write (rapport as text) to file p2r
       
   on error MsgErr number NroErr
       if NroErr is not -128 then
           beep 2
           activate
           if my parleAnglais() then
               display dialog "" & NroErr & " : " & MsgErr with icon 0 buttons {"Oops"} giving up after 20
           else
               display dialog "" & NroErr & " : " & MsgErr with icon 0 buttons {" Vu "} giving up after 20
           end if
       end if -- NroErr is…
       return
   end try
   my nettoie()
   if my parleAnglais() then
       my afficheLeMessage("Process is done!")
   else
       my afficheLeMessage("Traitement terminé !")
   end if
end main

--=============

on afficheLeMessage(m)
   beep 1
   activate
   if my parleAnglais() then
       display dialog m buttons {" OK "} default button 1 giving up after 10
   else
       display dialog m buttons {" Vu "} default button 1 giving up after 10
   end if
end afficheLeMessage

--===========

on exploreTraite(elem, ptree) (*
elem est un alias
• elem is an alias *)

   local elem_, laClasse, flag
   
   set elem_ to elem as text
   tell application "System Events" to tell disk item elem_
       set {origName, laClasse, dossierDeStockage} to {name, class as text, path of container}
   end tell
   if laClasse is in {"file package", "«class cpkg»"} then (*
Attention, un package EST un dossier "spécial".
• Caution, a package IS a "special" folder. *)

       if my parleAnglais() then
           set rapport to rapport & ">>> " & dossierDeStockage & nom_alt & ":" & origName & " is a Package" & return
       else
           set rapport to rapport & ">>> " & dossierDeStockage & nom_alt & ":" & origName & " est un Package" & return
       end if
       my |déménage|(nom_alt, elem_)
   else if laClasse is in {"folder", "«class cfol»"} then (*
traitement des dossiers à l'exclusion de ceux que le script crée.
• treat the folders minus those created by the script itself. *)

       if origName is not in {nom_GR, nom_alt} then my ExploreUnDossier(elem_, ptree)
   else if my testStuffit(elem) is true then (*
Rejette fichier Stuffit déguisé en AppleWorks.
• Skip Stuffit file disguised as AppleWorks *)

       if my parleAnglais() then
           set rapport to rapport & ">>> " & dossierDeStockage & nom_alt & ":" & origName & " is a Stuffit file" & return
       else
           set rapport to rapport & ">>> " & dossierDeStockage & nom_alt & ":" & origName & " est un fichier Stuffit" & return
       end if
       my |déménage|(nom_alt, elem_)
   else
       set flag to my testeAWsignature(elem)
       
       if theApp is in {"Pages", "Numbers"} then
           if flag = 4 then (*
C'est un Tableur ou un Tdt AppleWorks 6.
• It's an AppleWorks 6 SS or WP *)

               my AW6to_iWork(elem_)
           else if flag = 2 then (*
C'est un "vieux" Tableur ou Tdt AppleWorks.
• It's an "old" AppleWorks SS or WP *)

               if my parleAnglais() then
                   if theApp is "Pages" then
                       set rapport to rapport & ">>> " & dossierDeStockage & nom_alt & ":" & origName & " is an old AW WP file which can't be exported" & return
                   else
                       set rapport to rapport & ">>> " & dossierDeStockage & nom_alt & ":" & origName & " is an old AW SS file which can't be exported" & return
                   end if
               else
                   set rapport to rapport & ">>> " & dossierDeStockage & nom_alt & ":" & origName & " est un ancien fichier AW non exportable" & return
               end if
               my |déménage|(nom_alt, elem_)
           else if flag = 3 then
               (*
Logically we don't come here *)

               if my parleAnglais() then
                   set rapport to rapport & ">>> " & dossierDeStockage & nom_alt & ":" & origName & " is an AW6 file which can't be exported" & return
               else
                   set rapport to rapport & ">>> " & dossierDeStockage & nom_alt & ":" & origName & " est un fichier AW6 non exportable" & return
               end if
               my |déménage|(nom_alt, elem_)
           else if flag = 1 then
               (*
Logically we don't come here *)

               if my parleAnglais() then
                   set rapport to rapport & ">>> " & dossierDeStockage & nom_alt & ":" & origName & " is an old AW file which can't be exported" & return
               else
                   set rapport to rapport & ">>> " & dossierDeStockage & nom_alt & ":" & origName & " est un ancien fichier AW non exportable" & return
               end if
               my |déménage|(nom_alt, elem_)
           else
               (*
Logically we don't come here *)

               if my parleAnglais() then
                   set rapport to rapport & ">>> " & dossierDeStockage & nom_alt & ":" & origName & " isn’t an AW file" & return
               else
                   set rapport to rapport & ">>> " & dossierDeStockage & nom_alt & ":" & origName & " n’est pas un fichier AW" & return
               end if
               my |déménage|(nom_alt, elem_)
           end if -- flag…
       else if theApp is "-" then
           (*
• It's an AW Draw file *)

           if my parleAnglais() then
               set rapport to rapport & ">>> " & dossierDeStockage & nom_alt & ":" & origName & " is an AW Draw file" & return
           else
               set rapport to rapport & ">>> " & dossierDeStockage & nom_alt & ":" & origName & " est un fichier vectoriel AW" & return
           end if
           my |déménage|(nom_GR, elem_)
       else
           (*
• It's a file which can't be treated *)

           if my parleAnglais() then
               set rapport to rapport & ">>> can’t treat " & dossierDeStockage & nom_alt & ":" & origName & return
           else
               set rapport to rapport & ">>> impossible de traiter " & dossierDeStockage & nom_alt & ":" & origName & return
           end if
           my |déménage|(nom_alt, elem_)
       end if -- theApp…
   end if -- laClasse is …
end exploreTraite

--=====

on |déménage|(nom_doss, un_item)
   set reserve to dossierDeStockage & nom_doss
   tell application "System Events"
       if not (exists folder reserve) then make new folder at end of folder dossierDeStockage with properties {name:nom_doss}
   end tell
   do shell script "mv " & quoted form of POSIX path of un_item & space & quoted form of POSIX path of reserve
end |déménage|

--===========

on testeAWsignature(f)
   local flag, deb280, versionNum, marqueur
   
   set deb280 to (read f from 1 for 280)
   if (text 5 thru 8 of deb280) is "BOBO" then (* it's an AppleWorks document *)
       set flag to 1
       set versionNum to ASCII number of (character 1 of deb280)
       if versionNum = 6 then
           set marqueur to 279 -- cas de la version AW6
           set flag to 3
       else if versionNum = 5 then
           set marqueur to 269 -- cas de la version AW5/CW5
       else if versionNum = 4 then
           set marqueur to 258 -- cas de la version CW4
       else if versionNum = 3 then
           set marqueur to 250 -- cas de la version CW3
       else if versionNum = 2 then
           set marqueur to 250 -- cas de la version CW2
       else if versionNum = 1 then
           set marqueur to 244 -- cas de la version CW1
       else
           set marqueur to 0
       end if -- character 1 …
       (* The character at offset marqueur is a type signature
0 = CWGR
1 = CWWP
2 = CWSS
3 = CWDB
4 = CWPT
5 = CWPR
*)

       set maybe to ASCII number (character marqueur of deb280)
       if maybe > 3 then
           set {theApp, theExt, flag} to {"", "", 0}
       else
           set {theApp, theExt} to item (1 + maybe) of {{"-", "-"}, {"Pages", "pages"}, {"Numbers", "numbers"}}
           if marqueur > 0 then set flag to flag + 1 (* -> 2 ou 4 *)
       end if
   else
       set {theApp, theExt, flag} to {"", "", 0}
   end if -- (text 5 thru…
   return flag (*
   0 = pas AppleWorks
   1 = oldAW pas xxx
   2 = oldAW xxx
   3 = AW6 pas xxx
   4 = AW6 xxx *)

end testeAWsignature

--===========

on testStuffit(f)
   return (read f from 1 for 100) contains "Stuffit"
end testStuffit

--===========

on ExploreUnDossier(dossier, ptree)
   local nomElement, cheminElement
   repeat with nomElement in list folder dossier without invisibles
       try
           set cheminElement to dossier & nomElement
           tell application "Finder" to set c to name of (dossier as alias)
           my exploreTraite(cheminElement as alias, ptree & c & ":")
       on error
           (*
• It's a folder which can't be treated *)

           if my parleAnglais() then
               set rapport to rapport & ">>> " & dossier & " contains a file with an illegal name" & return
           else
               set rapport to rapport & ">>> " & dossier & " contient un fichier au nom incorrect" & return
           end if
           my |déménage|(nom_alt, dossier)
       end try
   end repeat
end ExploreUnDossier

--=====

on AW6to_iWork(leCheminAW6_UniText)
   local p, flag, nom_de_p, ext_de_p, nouveauNom
   
   set p to leCheminAW6_UniText as alias
   tell application "System Events" to tell disk item leCheminAW6_UniText
       set {nom_de_p, ext_de_p} to {name, name extension}
   end tell -- System Events…
   
   if ext_de_p is not "" then set nom_de_p to text 1 thru -(2 + (length of ext_de_p)) of nom_de_p
   set nouveauNom to nom_de_p & "." & theExt
   
   try (* 1 *)
       set flag to false
       tell application theApp
           try
               set oldCnt to my getNbWindows()
           on error
               set oldCnt to 0
           end try
           open p
           repeat 300 times (*
Attends que le fichier soit réellement ouvert.
• Wait until the file is really open *)

               if my getNbWindows() > oldCnt then
                   set flag to true
                   exit repeat
               end if
           end repeat
       end tell -- to theApp
       if flag is false then error number 8888
   on error
       if NroErr = 8888 then
           if my parleAnglais() then
               set rapport to rapport & ">>> " & theApp & " can’t read " & leCheminAW6_UniText & return
           else
               set rapport to rapport & ">>> " & theApp & " n'a pas pu lire " & leCheminAW6_UniText & return
           end if
       else
           if my parleAnglais() then
               set rapport to rapport & ">>> " & theApp & " can’t open " & leCheminAW6_UniText & return
           else
               set rapport to rapport & ">>> " & theApp & " n'a pas ouvert " & leCheminAW6_UniText & return
           end if
       end if
       my |déménage|(nom_alt, leCheminAW6_UniText)
       (*
• can't achieve the remaining tasks *)

       return
   end try (* 1 *)
   
   set nouveauChemin to dossierDeStockage & nouveauNom
   tell application "System Events" to if exists (disk item nouveauChemin) then set name of disk item nouveauChemin to nom_de_p & my horoDateur(modification date of disk item nouveauChemin) & "." & theExt (* name stamped *)
   try (* 2 *)
       tell application theApp
           save document 1 in nouveauChemin
           close document 1
       end tell -- theApp
       
       
       
       
       (*
       try
           tell application "System Events" to delete disk item leCheminAW6_UniText
       end try
       *)

       
       
       
       
       
   on error
       if my parleAnglais() then
           set rapport to rapport & ">>> " & theApp & " can’t export " & leCheminAW6_UniText & return
           els
           set rapport to rapport & ">>> " & theApp & " n'a pas exporté " & leCheminAW6_UniText & return
       end if
       my |déménage|(nom_alt, leCheminAW6_UniText)
   end try (* 2 *)
end AW6to_iWork

--=====
(*
• Build a stamp from the modification date_time
*)

on horoDateur(une_date)
   tell une_date to return "_" & (((its year) * 10000 + (its month) * 100 + (its day)) as text) & "_" & text 2 thru -1 of ((1000000 + (its hours) * 10000 + (its minutes) * 100 + (its seconds)) as text)
end horoDateur

--=====
(*
• Wait that the file is completely written on disk
*)

on wait4AWfile(p)
   local oldSize, newSize
   set oldSize to 0
   repeat
       tell application "System Events" to set newSize to physical size of file p
       if oldSize < newSize then
           set oldSize to newSize
       else
           exit repeat
       end if
   end repeat
end wait4AWfile

--=====

on getNbWindows()
   tell application "System Events" to tell (first process whose title is theApp) to return count of windows
end getNbWindows

--=====

on parleAnglais()
   return (do shell script "defaults read 'Apple Global Domain' AppleLocale") does not start with "fr_"
end parleAnglais

--=====

on nettoie() (*
pour ne pas stocker dans le fichier script
• So it will not be stored in the script file *)

   set dossierDeStockage to ""
   set rapport to ""
   set theApp to ""
   set theExt to ""
   set nomDuRapport to ""
   set nom_GR to ""
   set nom_alt to ""
end nettoie

--=====

--[/SCRIPT]

Offline

 

#5 2012-04-04 03:26:03 am

Yvan Koenig
Member
Registered: 2006-09-14
Posts: 2418

Re: Batch convert files recursively

Thanks

I looked back into you script.

(1) It's not a recursive one. It's just a simple loop which doesn't treat files stored in subfolder of the treated folder.
(2) For tests I rebuilt it this way :

Applescript:


on run
   choose file with multiple selections allowed
   my doyourduty(result as list)
end run

on open theFiles
   my doyourduty(theFiles)
end open

on doyourduty(theFiles)
   
   tell application "Pages"
       repeat with aFile in theFiles
           if (aFile as text) ends with ".cwk" then
               open aFile
               set docName to name of front document
               -- Remove .cwk extension.
               set prevTIDs to AppleScript's text item delimiters
               set AppleScript's text item delimiters to ".cwk"
               -- Add .pages extension.
               set docName to first text item of docName & ".pages"
               set AppleScript's text item delimiters to prevTIDs
               -- Get folder that dropped file exists in.
               tell application "Finder"
                   set sourceFolder to (container of aFile) as Unicode text
               end tell -- Finder
               -- Save file to folder that dropped file exists in.
               set docPathAndName to sourceFolder & docName
               save front document in docPathAndName
               close front document
           end if
       end repeat
   end tell
end doyourduty

With this structure, I was able to get the log report.
As the run handler get a list of files, everything work well.
This let me remember some words of your original message :
"which is meant to have a folder dragged onto it to execute"

Your code is unable to do the wanted duty if you drag a folder onto it.
It's designed to apply if you drop on it files selected in a folder.

Yvan KOENIG (VALLAURIS, France) mercredi 4 avril 2012 10:25:55

Offline

 

#6 2012-04-04 04:54:17 am

StefanK
Member
From: St. Gallen, Switzerland
Registered: 2006-10-21
Posts: 11324
Website

Re: Batch convert files recursively

Yvan Koenig wrote:

Your code is unable to do the wanted duty if you drag a folder onto it.
It's designed to apply if you drop on it files selected in a folder.

This is a recursive version which considers also (dragged) folders

Applescript:


on run
   doyourduty(choose file with multiple selections allowed)
end run

on open droppedItems
   doyourduty(droppedItems)
end open

on doyourduty(theItems)
   repeat with anItem in theItems
       tell application "Finder"
           set {name:fileName, name extension:nameExtension, class:itemClass, container:parentFolder} to item (anItem as text)
           set isFolder to itemClass is folder
       end tell
       if isFolder then
           tell application "Finder" to set itemList to items of anItem
           doyourduty(itemList)
       else
           if nameExtension is "cwk" then
               tell application "Pages"
                   open (anItem as alias)
                   -- Save file to folder that dropped file exists in.
                   set docPathAndName to (parentFolder as text) & text 1 thru -4 of fileName & "pages"
                   save front document in docPathAndName
                   close front document
               end tell
           end if
       end if
   end repeat
end doyourduty

Last edited by StefanK (2012-04-04 04:55:50 am)


regards

Stefan

Offline

 

Board footer

Powered by FluxBB

[ Generated in 0.153 seconds, 11 queries executed ]

RSS (new topics) RSS (active topics)