Guides and Sample Code

Developer

Mac Automation Scripting Guide

On This Page

Reading and Writing Files

Scripts are often designed to write data to files such as logs or backups. The Standard Additions scripting addition contains a number of commands that make it possible to read and write files.

Writing to a File

The handlers in Listing 16-1 and Listing 16-2 safely write data to disk, creating a new file if the targeted file doesn’t already exist. Provide the text to write, a target file path, and indicate whether to overwrite existing content. If you choose not to overwrite existing content, then the text provided is appended to any existing content.

APPLESCRIPT

Open in Script Editor

Listing 16-1AppleScript: Handler that writes text to a file
  1. on writeTextToFile(theText, theFile, overwriteExistingContent)
  2. try
  3. -- Convert the file to a string
  4. set theFile to theFile as string
  5. -- Open the file for writing
  6. set theOpenedFile to open for access file theFile with write permission
  7. -- Clear the file if content should be overwritten
  8. if overwriteExistingContent is true then set eof of theOpenedFile to 0
  9. -- Write the new content to the file
  10. write theText to theOpenedFile starting at eof
  11. -- Close the file
  12. close access theOpenedFile
  13. -- Return a boolean indicating that writing was successful
  14. return true
  15. -- Handle a write error
  16. on error
  17. -- Close the file
  18. try
  19. close access file theFile
  20. end try
  21. -- Return a boolean indicating that writing failed
  22. return false
  23. end try
  24. end writeTextToFile

JAVASCRIPT

Open in Script Editor

Listing 16-2JavaScript: Function that writes text to a file
  1. var app = Application.currentApplication()
  2. app.includeStandardAdditions = true
  3. function writeTextToFile(text, file, overwriteExistingContent) {
  4. try {
  5. // Convert the file to a string
  6. var fileString = file.toString()
  7. // Open the file for writing
  8. var openedFile = app.openForAccess(Path(fileString), { writePermission: true })
  9. // Clear the file if content should be overwritten
  10. if (overwriteExistingContent) {
  11. app.setEof(openedFile, { to: 0 })
  12. }
  13. // Write the new content to the file
  14. app.write(text, { to: openedFile, startingAt: app.getEof(openedFile) })
  15. // Close the file
  16. app.closeAccess(openedFile)
  17. // Return a boolean indicating that writing was successful
  18. return true
  19. }
  20. catch(error) {
  21. try {
  22. // Close the file
  23. app.closeAccess(file)
  24. }
  25. catch(error) {
  26. // Report the error is closing failed
  27. console.log(`Couldn't close file: ${error}`)
  28. }
  29. // Return a boolean indicating that writing was successful
  30. return false
  31. }
  32. }

Listing 16-3 and Listing 16-4 show how to call the handlers in Listing 16-1 and Listing 16-2 to write text content to a file on the Desktop, replacing any existing content in the file.

APPLESCRIPT

Open in Script Editor

Listing 16-3AppleScript: Calling a handler to write text to a file
  1. set this_story to "Once upon a time in Silicon Valley..."
  2. set theFile to (((path to desktop folder) as string) & "MY STORY.txt")
  3. writeTextToFile(this_story, theFile, true)

JAVASCRIPT

Open in Script Editor

Listing 16-4JavaScript: Calling a function to write text to a file
  1. var story = "Once upon a time in Silicon Valley..."
  2. var desktopString = app.pathTo("desktop").toString()
  3. var file = `${desktopString}/MY STORY.txt`
  4. writeTextToFile(story, file, true)

Listing 16-5 and Listing 16-6 show how Listing 16-1 and Listing 16-2 could be called to insert dated log entries into a log file.

APPLESCRIPT

Open in Script Editor

Listing 16-5AppleScript: Calling a handler to write an entry to a log file
  1. set theText to ((current date) as string) & space & "STATUS OK" & return
  2. set theFile to (((path to desktop folder) as string) & "MY LOG FILE.log")
  3. writeTextToFile(theText, theFile, false)

JAVASCRIPT

Open in Script Editor

Listing 16-6JavaScript: Calling a function to write an entry to a log file
  1. var dateString = Date().toString()
  2. var desktopString = app.pathTo("desktop").toString()
  3. var text = `${dateString} STATUS OK\n\n`
  4. var file = `${desktopString}/MY LOG FILE.log`
  5. writeTextToFile(text, file, false)

In practice, this technique could be used to maintain a log when script errors occur. Listing 16-7 and Listing 16-8 are try statements, which can be wrapped around custom script code in order to log any script errors to a file in the ~/Library/Logs/ folder of the current user’s home directory.

APPLESCRIPT

Open in Script Editor

Listing 16-7AppleScript: Example of a try statement that writes an entry to a log file when an error occurs
  1. try
  2. -- Your custom script code goes here
  3. on error theErrorMessage number theErrorNumber
  4. set theError to "Error: " & theErrorNumber & ". " & theErrorMessage & return
  5. set theLogFile to ((path to library folder from user domain) as string) & "Logs:Script Error Log.log"
  6. my writeTextToFile(theError, theLogFile, false)
  7. end try

JAVASCRIPT

Open in Script Editor

Listing 16-8JavaScript: Example of a try statement that writes an entry to a log file when an error occurs
  1. try {
  2. // Your custom script code goes here
  3. }
  4. catch (error) {
  5. var errorString = `Error: ${error.message}\n\n`
  6. var logFile = app.pathTo("library folder", { from: "user domain" }).toString() + "/Logs/Script Error Log.log"
  7. writeTextToFile(errorString, logFile, false)
  8. }

Reading a File

The handlers in Listing 16-9 and Listing 16-10 read the contents of a specified file.

APPLESCRIPT

Open in Script Editor

Listing 16-9AppleScript: Handler that reads the contents of a file
  1. on readFile(theFile)
  2. -- Convert the file to a string
  3. set theFile to theFile as string
  4. -- Read the file and return its contents
  5. return read file theFile
  6. end readFile

JAVASCRIPT

Open in Script Editor

Listing 16-10JavaScript: Function that reads the contents of a file
  1. var app = Application.currentApplication()
  2. app.includeStandardAdditions = true
  3. function readFile(file) {
  4. // Convert the file to a string
  5. var fileString = file.toString()
  6. // Read the file and return its contents
  7. return app.read(Path(fileString))
  8. }

Listing 16-11 and Listing 16-12 show how to call the handlers in Listing 16-9 and Listing 16-10 to read a specified text file.

APPLESCRIPT

Open in Script Editor

Listing 16-11AppleScript: Calling a handler to read the contents of a file
  1. set theFile to choose file of type "txt" with prompt "Please select a text file to read:"
  2. readFile(theFile)
  3. --> Result: "Contents of the chosen file."

JAVASCRIPT

Open in Script Editor

Listing 16-12JavaScript: Calling a function to read the contents of a file
  1. var file = app.chooseFile({
  2. ofType: "txt",
  3. withPrompt: "Please select a text file to read:"
  4. })
  5. readFile(file)
  6. // Result: "Contents of the chosen file."

Reading and Splitting a File

The handlers in Listing 16-13 and Listing 16-14 read the contents of a specified text file, using a delimiter to split it into a list.

APPLESCRIPT

Open in Script Editor

Listing 16-13AppleScript: Handler for reading and splitting the contents of a file based on a delimiter
  1. on readAndSplitFile(theFile, theDelimiter)
  2. -- Convert the file to a string
  3. set theFile to theFile as string
  4. -- Read the file using a specific delimiter and return the results
  5. return read file theFile using delimiter {theDelimiter}
  6. end readAndSplitFile

JAVASCRIPT

Open in Script Editor

Listing 16-14JavaScript: Function for reading and splitting the contents of a file based on a delimiter
  1. var app = Application.currentApplication()
  2. app.includeStandardAdditions = true
  3. function readAndSplitFile(file, delimiter) {
  4. // Convert the file to a string
  5. var fileString = file.toString()
  6. // Read the file using a specific delimiter and return the results
  7. return app.read(Path(fileString), { usingDelimiter: delimiter })
  8. }

Listing 16-15 and Listing 16-16 shows how to call the handlers in Listing 16-13 and Listing 16-14 to read the paragraphs of a chosen log file.

APPLESCRIPT

Open in Script Editor

Listing 16-15AppleScript: Calling a handler to read and split the contents of a file based on a delimiter
  1. set theFile to choose file of type "log" with prompt "Please select a log file:"
  2. readAndSplitFile(theFile, return)
  3. --> Result: {"Log entry 1", "Log entry 2", ... }

JAVASCRIPT

Open in Script Editor

Listing 16-16JavaScript: Calling a function to read and split the contents of a file based on a delimiter
  1. var file = app.chooseFile({
  2. ofType: "log",
  3. withPrompt: "Please select a log file:"
  4. })
  5. readAndSplitFile(file, "\n")
  6. // Result: ["Log entry 1", "Log entry 2", ...]