Hi there,
how can I batch convert thousands of TextEdit .rtf documents in a folder and different subfolders with text formatted in Helvetica to Courier without opening the documents (El Capitan)?
Thanks for your help.
Hi there,
how can I batch convert thousands of TextEdit .rtf documents in a folder and different subfolders with text formatted in Helvetica to Courier without opening the documents (El Capitan)?
Thanks for your help.
Here is a draft script treating a single file.
The loop treating several file is left as an exercise
set original to choose file of type {"public.rtf"} # returns an alias
set pathAsList to my decoupe(original as text, ":")
set commonFolder to my recolle(items 1 thru -2 of pathAsList, ":") & ":"
set origName to item -1 of pathAsList
set newName to text 1 thru -5 of origName & " modified.rtf"
set newDoc to commonFolder & newName
set origText to read original # original is an alias
set newText to my remplace(origText, "charset0 Helvetica;", "charset0 Courier;")
my writeto(newDoc, newText, text, false)
#=====
on decoupe(t, d)
local oTIDs, l
set {oTIDs, AppleScript's text item delimiters} to {AppleScript's text item delimiters, d}
set l to text items of t
set AppleScript's text item delimiters to oTIDs
return l
end decoupe
#=====
on recolle(l, d)
local oTIDs, t
set {oTIDs, AppleScript's text item delimiters} to {AppleScript's text item delimiters, d}
set t to l as text
set AppleScript's text item delimiters to oTIDs
return t
end recolle
#=====
(*
replaces every occurences of d1 by d2 in the text t
*)
on remplace(t, d1, d2)
local oTIDs, l
set {oTIDs, AppleScript's text item delimiters} to {AppleScript's text item delimiters, d1}
set l to text items of t
set AppleScript's text item delimiters to d2
set t to l as text
set AppleScript's text item delimiters to oTIDs
return t
end remplace
#=====
(*
Handler borrowed to Regulus6633 - http://macscripter.net/viewtopic.php?id=36861
*)
on writeto(targetFile, theData, dataType, apendData)
-- targetFile is the path to the file you want to write
-- theData is the data you want in the file.
-- dataType is the data type of theData and it can be text, list, record etc.
-- apendData is true to append theData to the end of the current contents of the file or false to overwrite it
try
set targetFile to targetFile as «class furl»
set openFile to open for access targetFile with write permission
if not apendData then set eof of openFile to 0
write theData to openFile starting at eof as dataType
close access openFile
return true
on error
try
close access targetFile
end try
return false
end try
end writeto
#=====
Yvan KOENIG running El Capitan 10.11.5 in French (VALLAURIS, France) mercredi 13 juillet 2016 16:46:26
Thank you very much Yvan. I will try that exercise
Here are two proposed ways to do the job.
Version 1 :
--[SCRIPT batch_change Helvetica into Courier.app]
(*
Based upon an old recursive skeleton using only old fashioned Applescript features.
Yvan KOENIG (VALLAURIS, France)
2016/07/13
*)
property changeName : true
(* true = wxyz.rtf will be saved as wxyz modified.rtf
false = save with the original name
*)
property theExt : "rtf"
script o
property msg1 : "" -- globale
property msg3 : "" -- globale
property msg90 : "" -- globale
property msg91 : "" -- globale
property msg92 : "" -- globale
property msg98 : "" -- globale
property msg99 : "" -- globale
property report : "" -- globale
end script
--=====
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 *)
tell application (path to frontmost application as string) to set aFolder to choose folder
open {aFolder}
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) *)
local elem, reportName, p2d, p2r, MsgErr, NroErr
my buildMessages()
my displayMsg(o's msg1) (*
Éviter de cliquer.
¢ Don't click. *)
try
repeat with elem in sel
set elem to elem as text
try
my scanAndTreat(elem, "")
end try
end repeat
if o's report = "" then set o's report to o's msg90 (*
crée un fichier texte sur le Bureau *)
set p2r to (path to desktop as text) & "report_Helvetica2Courier.txt"
my writeto(p2r, (o's report), text, false)
my displayMsg(o's msg3) (*
Traitement terminé
¢ Export done. *)
on error MsgErr number NroErr
if NroErr is not -128 then
beep 2
tell application (path to frontmost application as string) to ¬
display dialog "" & NroErr & " : " & MsgErr with icon 0 buttons {o's msg99} giving up after 20
end if -- NroErr is.
end try
end open
--=====
on displayMsg(m)
beep 1
tell application (path to frontmost application as string)
display dialog m buttons {o's msg98} default button 1 giving up after 10
end tell
end displayMsg
--=====
on scanAndTreat(elem, ptree) (*
elem est un Unicode text
¢ elem is an Unicode text *)
local cl_, nameExt_
tell application "System Events" to tell disk item elem
set cl_ to (get its class) as text
try
set nameExt_ to name extension
on error
set nameExt_ to ""
end try
end tell -- System Events
if nameExt_ is theExt then
my treatADocument(elem) (*
C'est un fichier Rtf.
¢ It's a Rtf document *)
else if cl_ is in {"file package", "«class cpkg»"} then
set o's report to o's report & elem & o's msg91 & return (*
"Package", Attention, un package EST un dossier "spécial".
¢ Caution, a package IS a "special" folder. *)
else if cl_ is in {"folder", "«class cfol»"} then
my scanAfolder(elem, ptree)
else
set o's report to o's report & elem & o's msg92 & return (*
"Pas un document Pages".
¢ "Not a Pages document" *)
end if -- cl_ is .
end scanAndTreat
--=====
on scanAfolder(aFolder, ptree)
local theElems, anElem, elemName, C
if aFolder does not end with ":" then set aFolder to aFolder & ":"
tell application "System Events"
set theElems to disk items of folder aFolder whose visible is true
--repeat with anElem in (disk items of folder aFolder whose visible is true)
repeat with anElem in theElems
set elemName to name of anElem
set C to name of folder aFolder
my scanAndTreat((aFolder & elemName), ptree & C & ":")
end repeat
end tell
end scanAfolder
--=====
on treatADocument(sourcePath) (*
¢ sourcePath is of class Unicode text *)
local newDoc, origText, newText
if changeName then
set newDoc to text 1 thru -5 of sourcePath & " modified.rtf"
else
set newDoc to sourcePath # uses the original pathname as destination one
end if
set origText to read file sourcePath # sourcePath is an Unicode text
if origText contains "charset0 Helvetica;" then
set newText to my remplace(origText, "charset0 Helvetica;", "charset0 Courier;")
my writeto(newDoc, newText, text, false)
end if
end treatADocument
--=====
on buildMessages()
if (do shell script "defaults read 'Apple Global Domain' AppleLocale") starts with "fr_" then
set o's msg1 to "Éviter de cliquer durant l'exécution du script" & return & "sauf s'il le demande."
set o's msg3 to "Traitement terminé."
set o's msg90 to "Modifications réussies sans incident."
set msg91 to "est un Package"
set msg92 to "n'est pas un document " & theExt
set o's msg98 to " Vu "
set o's msg99 to " Vu "
else
set o's msg1 to "Don't click when the script is running." & return & "Except, of course, if it ask for."
set o's msg3 to "Changes done."
set o's msg90 to "No problem during the modification process."
set msg91 to "is a Package"
set msg92 to "is not a " & theExt & " document"
set o's msg98 to " OK "
set o's msg99 to "Oops"
end if
set o's msg91 to " ### " & msg91 & " ###"
set o's msg92 to " ### " & msg92 & " ###"
end buildMessages
#=====
on decoupe(t, d)
local oTIDs, l
set {oTIDs, AppleScript's text item delimiters} to {AppleScript's text item delimiters, d}
set l to text items of t
set AppleScript's text item delimiters to oTIDs
return l
end decoupe
#=====
on recolle(l, d)
local oTIDs, t
set {oTIDs, AppleScript's text item delimiters} to {AppleScript's text item delimiters, d}
set t to l as text
set AppleScript's text item delimiters to oTIDs
return t
end recolle
#=====
(*
replaces every occurences of d1 by d2 in the text t
*)
on remplace(t, d1, d2)
local oTIDs, l
set {oTIDs, AppleScript's text item delimiters} to {AppleScript's text item delimiters, d1}
set l to text items of t
set AppleScript's text item delimiters to d2
set t to l as text
set AppleScript's text item delimiters to oTIDs
return t
end remplace
#=====
(*
Handler borrowed to Regulus6633 - http://macscripter.net/viewtopic.php?id=36861
*)
on writeto(targetFile, theData, dataType, apendData)
-- targetFile is the path to the file you want to write
-- theData is the data you want in the file.
-- dataType is the data type of theData and it can be text, list, record etc.
-- apendData is true to append theData to the end of the current contents of the file or false to overwrite it
try
set targetFile to targetFile as «class furl»
set openFile to open for access targetFile with write permission
if not apendData then set eof of openFile to 0
write theData to openFile starting at eof as dataType
close access openFile
return true
on error
try
close access targetFile
end try
return false
end try
end writeto
#=====
--[/SCRIPT]
Version 2 : use Shane STANLEY’s BridgePlus
use scripting additions
use framework "Foundation"
use script "BridgePlus"
property changeName : true
script o
property theFiles : {}
end script
on run
load framework
my germaine()
end run
#=====
on getItemsIn:posixPathOfFolder searchedExtensions:theExtensions
set theResults to current application's SMSForder's resourceValuesForKeys:{current application's NSURLPathKey} forFilesIn:posixPathOfFolder recursive:true skipHidden:true skipInsidePackages:true
if theExtensions is not {} then
set thePred to (current application's NSPredicate's predicateWithFormat:"%K.pathExtension IN[c] %@" argumentArray:{current application's NSURLPathKey, theExtensions})
set theResults to (theResults's filteredArrayUsingPredicate:thePred)
end if
set thePaths to (theResults's valueForKey:(current application's NSURLPathKey))
set o's theFiles to thePaths as list # Use the well known tip fasting use of lists as the asker wrote upon 4000 files
end getItemsIn:searchedExtensions:
#=====
on decoupe(t, d)
local oTIDs, l
set {oTIDs, AppleScript's text item delimiters} to {AppleScript's text item delimiters, d}
set l to text items of t
set AppleScript's text item delimiters to oTIDs
return l
end decoupe
#=====
on recolle(l, d)
local oTIDs, t
set {oTIDs, AppleScript's text item delimiters} to {AppleScript's text item delimiters, d}
set t to l as text
set AppleScript's text item delimiters to oTIDs
return t
end recolle
#=====
(*
replaces every occurences of d1 by d2 in the text t
*)
on remplace(t, d1, d2)
local oTIDs, l
set {oTIDs, AppleScript's text item delimiters} to {AppleScript's text item delimiters, d1}
set l to text items of t
set AppleScript's text item delimiters to d2
set t to l as text
set AppleScript's text item delimiters to oTIDs
return t
end remplace
#=====
(*
Handler borrowed to Regulus6633 - http://macscripter.net/viewtopic.php?id=36861
*)
on writeto(targetFile, theData, dataType, apendData)
-- targetFile is the path to the file you want to write
-- theData is the data you want in the file.
-- dataType is the data type of theData and it can be text, list, record etc.
-- apendData is true to append theData to the end of the current contents of the file or false to overwrite it
try
set targetFile to targetFile as «class furl»
set openFile to open for access targetFile with write permission
if not apendData then set eof of openFile to 0
write theData to openFile starting at eof as dataType
close access openFile
return true
on error
try
close access targetFile
end try
return false
end try
end writeto
#=====
on germaine()
set posixPathOfFolder to POSIX path of (choose folder)
# Builds the list of RTF files stored in the folder and its subfolders
my getItemsIn:posixPathOfFolder searchedExtensions:{"rtf"} # Returns a list of posix paths
repeat with aFile in o's theFiles
if changeName then
set newDoc to text 1 thru -5 of aFile & " modified.rtf"
else
set newDoc to aFile # uses the original pathname as destination one
end if
# Why is the syntax below failing in Script Editor ?
-- set origText to read (POSIX file aFile) # "Impossible de convertir current application en type file." number -1700 from current application to file
# This alternate syntax works in Script Editor
set origText to read (get POSIX file aFile) # CAUTION, get is required here
if origText contains "charset0 Helvetica;" then
set newText to my remplace(origText, "charset0 Helvetica;", "charset0 Courier;")
my writeto(newDoc, newText, text, false)
end if
end repeat
end germaine
#=====
Main difference : the first one treat files when it reach them in there original location.
The second one builds a list of the files in s single call then treat the listed files.
As the list may be long it uses the good old tip storing the list in a script object.
This late one is also a recursive one but this time the recursive part is treated by the system itself which is more efficient than AppleScript to do that.
Yvan KOENIG running El Capitan 10.11.5 in French (VALLAURIS, France) jeudi 14 juillet 2016 16:02:05
Fantastic Yvan. Thank you very much. I see I have a lot to learn
Is there a chance to keep the tags and comments of the files?
Thanks.
If you choose the option : property changeName : false, the tags and the comments are kept.
If you choose the option : property changeName : true, the tags and comments are dropped.
Yvan KOENIG running El Capitan 10.11.5 in French (VALLAURIS, France) jeudi 14 juillet 2016 19:36:35
Awesome! Converted the font family in more than 7000 files in about 1:23 min.
Thank you!
Thanks for the feedback.
Yvan KOENIG running El Capitan 10.11.5 in French (VALLAURIS, France) jeudi 14 juillet 2016 20:28:22