I'm trying to write content to a file, /tmp/test.txt with AppleScript.
If the file doesn't exist, I want to create it.
If it does exist, I want to replace the contents.
This is proving quite difficult because AppleScript has a different syntax for creating a new file versus writing to an existing file. I also thought about deleting a file if it already exists, and then creating it, but AppleScript will move things to the trash by default and so even that is rather complicated.
The data I am going to write to the file may have a lot of special characters in it, so I don't really want to do something like do shell script "cat " + data + " > /tmp/txt.txt" because I am unaware of any escapeshellarg for AppleScript.
Below is what I have so far but I'm getting an error:
Can't make file "Macintosh HD:private:tmp:test.txt" into type reference.
I would really like to abstract this by improving the helper function write_to_file that I got here so that it would take care of creating the file if it does not exist.
my write_to_file("hello", "/tmp/test.txt", false)
on write_to_file(this_data, target_file, append_data)
try
if not (exists POSIX file target_file) then
make new document file at ("/tmp/" as POSIX file as alias) with properties {name:"test.txt", text:the_data}
end if
set the target_file to the target_file as POSIX file
set the open_target_file to open for access file target_file with write permission
if append_data is false then set eof of the open_target_file to 0
write this_data to the open_target_file starting at eof
close access the open_target_file
return true
on error e
try
display dialog e
close access file target_file
end try
return false
end try
end write_to_file
How can I create or replace a file using Applescript?
The first mistake you've made is mixing POSIX paths with HFS paths. A posix path is /tmp/test.txt and a hfs path to the same file will be Macintosh HD:tmp:test.txt if the name of the boot volume is Macintosh HD of course.
open for access file "Volume:Path:to:file.txt"
The second mistake is that for Mac OS X the /tmp folder is not the place to store temporary files. You will need administrator privileges to write there and the user will be prompted for username and password. It is stored in /var/folders and there is a folder created at login for each user, also with fast user switching. To access the path to this folder you should use the command path to temporary items. Temporary items will be removed between startups.
set theFile to (path to temporary items as string) & "test.txt"
The third mistake is that when you're using quoted form of you can use do shell script. Since AppleScript is unicode like the shell there is no such thing as that characters can't be handled by do shell script.
do shell script "/bin/echo -n " & (quoted form of "$#%^&*()#") & " > " POSIX path of theFile
At last you've made the mistake that you need to check for existence of a file. When you're using open for access command the file will be created when it doesn't exists for you. So the only code you need is:
set theFile to (path to temporary items as text) & "test.txt"
writeToFile(theFile, "Hello!", false)
writeToFile(theFile, (linefeed & "Goodbye!" as string), true)
on writeToFile(p, d, a)
try
set fd to open for access file p with write permission
if not a then set eof of fd to 0
write d to fd starting at (get eof of fd) as «class utf8»
close access fd
on error
close access file p
end try
end writeToFile
or using a do shell script which creates an UTF-8 file as well but the given path needs to be an POSIX path now
set theFile to (path to temporary items as text) & "test.txt"
writeToFile(POSIX path of theFile, "goodbye!", false)
writeToFile(POSIX path of theFile, (linefeed & "hello!" as string), true)
on writeToFile(p, d, a)
set cmd to "/bin/echo -n " & quoted form of d & " >"
if a then set cmd to cmd & ">"
do shell script cmd & space & quoted form of p
end writeToFile
Choose the one to your likings
Try:
my write_to_file("hello", "/tmp/test.txt", true)
on write_to_file(this_data, target_file, append_data)
try
tell application "System Events" to exists file target_file
if not the result then do shell script "> " & quoted form of target_file
set the open_target_file to open for access target_file with write permission
if append_data is false then set eof of the open_target_file to 0
write this_data to the open_target_file starting at eof
close access the open_target_file
return true
on error e
try
display dialog e
close access target_file
end try
return false
end try
end write_to_file
Related
Thanks to help received on these fine pages, my Mac has a little AppleScript to open a new session of Adobe Distiller.
do shell script "open -n -a " & quoted form of "Acrobat Distiller"
New question, asking for a small improvement to this. Can it be that if a .ps is dragged (or indeed, several are dragged) to the .app made by this .scpt, the new session of Distiller opens with that document (or those several documents)?
Thank you.
Save the following script as an application. If you run the application, it will let you choose files to open in a new instance; if you drop files on it, it will open them all in a new instance:
on run
set filesToOpen to choose file with multiple selections allowed
set fileListString to createUnixFileString(filesToOpen)
makeNewInstanceWithFiles(fileListString)
end run
on open droppedFiles
set fileListString to createUnixFileString(droppedFiles)
makeNewInstanceWithFiles(fileListString)
end open
on createUnixFileString(aList)
set fileString to ""
repeat with thisItem in aList
set fileString to fileString & " " & quoted form of (POSIX path of thisItem)
end repeat
return fileString
end createUnixFileString
on makeNewInstanceWithFiles(f)
do shell script "open -n -a " & quoted form of "Acrobat Distiller" & f
end makeNewInstanceWithFiles
If you want each file opened in a separate instance, call makeNewInstanceWithFiles for each file (making sure to get the posix path and include a space as a delimiter) instead of calling the createUnixFileString handler.
I'm trying to set up an Indesign script that copies the link information of a selected image and appends it to a text file to the desktop, if the text file does not exist it creates one. The link information is copied to the clipboard using a custom key command in inDesign. The problem is if I copy some text or an image beforehand, that text remains on the clipboard. Even though I copy new link info and set that clipboard to a variable.
I know this is an ugly script, I'm just good enough to get by, but barely.
Any suggestions on how to clear out the clipboard?
Thanks,
~David
--dialog box
display dialog "What do you need done" default answer "Remove Background"
set theAnswer to (text returned of result)
set this_story to "
------------------- " & theAnswer & " -------------------
"
set this_file to (((path to desktop folder) as string) & "Corrections.txt")
my write_to_file(this_story, this_file, false)
on write_to_file(this_data, target_file, append_data)
try
set the target_file to the target_file as string
set the open_target_file to open for access file target_file with write permission
if append_data is true then set eof of the open_target_file to 0
write this_data to the open_target_file starting at eof
close access the open_target_file
return true
on error
try
close access file target_file
end try
return false
end try
end write_to_file
--copy link information using keyboard short
activate application "Adobe InDesign CC 2015"
tell application "System Events" to keystroke "l" using {shift down, control down}
end
---
set myVar to the clipboard
my write_clip_file(myVar, this_file, false)
on write_clip_file(myVar, target_file, append_data)
try
set the target_file to the target_file as string
set the open_target_file to open for access file target_file with write permission
if append_data is true then set eof of the open_target_file to 0
write myVar to the open_target_file starting at eof
close access the open_target_file
return true
on error
try
close access file target_file
end try
return false
end try
end write_clip_file
Here is a cleaned up version of your script. You don't need to code the same handler twice... both times you right to the file, you can use the same handler. Also, I reversed the logic on the append_data variable, because you had the logic backwards. (if you DO append, then you DON'T set eof to 0 cause that erases the current content).
I don't know what function you're calling in InDesign, but sounds like it's placing the file path/link of a selected image onto the clipboard. When using the clipboard to get data and to place the data into a variable, it's a good practice to put some delays in the script, to avoid the script moving on to the next commands before the app you're working with finishes it's work. I'm betting that the problem you're having is that the script is proceeding before InDesign has finished copying to the clipboard. So, in this script, you can see I placed three delays surrounding the work with the clipboard. You can play with reducing the delay times to see what will still work reliably.
--dialog box
display dialog "What do you need done" default answer "Remove Background"
set theAnswer to (text returned of result)
set this_story to "
------------------- " & theAnswer & " -------------------
"
set this_file to (((path to desktop folder) as string) & "Corrections.txt")
my write_to_file(this_story, this_file, true)
--copy link information using keyboard short
tell application "Adobe InDesign CC 2015"
-- tell application "TextEdit" -- for testing purposes
activate
delay 0.9 -- give app time to come to the front before copying to clipboard
tell application "System Events" to keystroke "l" using {shift down, control down}
-- tell application "System Events" to keystroke "c" using {command down} -- for testing purposes
delay 0.9 -- wait til clipboard is copied before continuing with the script
end tell
set myVar to the clipboard
delay 0.1 -- wait til variable is pulled from clipboard before moving on
my write_to_file(myVar, this_file, true)
--
on write_to_file(this_data, target_file, append_data)
try
set the target_file to the target_file as string
set the open_target_file to open for access file target_file with write permission
if append_data is false then set eof of the open_target_file to 0
write this_data to the open_target_file starting at eof
close access the open_target_file
return true
on error
try
close access file target_file
end try
return false
end try
end write_to_file
Try this out and tweak it as you need to, and then let me know if anything is still not working.
Good evening all,
I am trying to understand why I can run the below script in Applescript Editor but am unable to successfully run it in an Xcode Cocoa-Applescript application.
Can someone please explain why this function will not run in Xcode and what I need to do to have it run correctly?
set this_data to ((current date) as string) & space & "WHY DOESN'T THIS LOG!!!!" & return
set this_file to (((path to desktop folder) as string) & "MY LOG FILE")
my write_to_file(this_data, this_file, true)
on write_to_file(this_data, target_file, append_data)
try
set the target_file to the target_file as string
set the open_target_file to open for access file target_file with write permission
if append_data is false then set eof of the open_target_file to 0
write this_data to the open_target_file starting at eof
close access the open_target_file
return true
on error
try
close access file target_file
end try
return false
end try
end write_to_file
This is one of the Xcode behaviours I can't explain, but it works if you add tell current application like this:
tell current application to set the open_target_file to open for access file target_file with write permission
It might be better to put the whole function in a tell current application block.
I'm creating simple script to convert mp3 files using shell script. I decided to automate my conversion using applescript.
Basically what I'm doing is selecting mp3 file then splitting that file using my command line and i want to create a folder where the file is located (script will create that for me).
Now I just need to figure out how to get a path to a folder of the file.
How do I do that in applescript?
Here is the script that I have so far:
set mp3FileToSplit to choose file without invisibles
set thepath to mp3FileToSplit as text
set theposix to POSIX path of thepath
tell application "Finder" to set file_name to (name of mp3FileToSplit)
do shell script "/opt/local/bin/mp3splt -t 3.00 -d " & quoted form of file_name & " " & quoted form of theposix
Right now what that script does is creating folder on the root of my hard drive and I need to be in the folder where the file is located.
Any help will be appreciated.
tell application "Finder"
set f to POSIX file "/private/etc/" as alias
POSIX path of ((folder of f) as alias) -- /private/
end tell
Or
do shell script "dirname /private/etc/" -- /private
In Script editor i have written a command to boot the JAR.
do shell script "cd /Desktop/RunJar/; java -jar RunMyJar.jar"
and Saved as script file as a Application. When i click on script file jar get run.
My requirement
I would like get the name of file that has been dropped onto the script file and would like to pass the name of that dropped file as an argument to my jar.
I have implemented this in Windows but could not working similar on MAC O.S.
On Windows
I have placed a BAT file to Boot JAR along with the absolute file name, that has been dropped on the bat file on windows. #echo %* will give me the list of files that has been dropped onto Batch file.
#echo %*
#pause
java -jar RunMyJar.jar %*
Similar i would like to implement in MAC O.S.
Thanks.
I found the following example at: Ben's AppleScript Snippets:
on open of finderObjects -- "open" handler triggered by drag'n'drop launches
repeat with i in (finderObjects) -- in case multiple objects dropped on applet
displayName(i) -- show file/folder's info
if folder of (info for i) is true then -- process folder's contents too
tell application "Finder" to set temp to (entire contents of i)
repeat with j in (temp)
display dialog j as string -- example of doing something with each item
end repeat
end if
end repeat
end open
You can also easily modify my answer to a similar question:
on open of theFiles -- Executed when files are dropped on the script
set fileCount to (get count of items in theFiles)
repeat with thisFile from 1 to fileCount
set theFile to item thisFile of theFiles
set theFileAlias to theFile as alias
tell application "Finder"
set fileInfo to info for theFileAlias
set fileName to name of fileInfo
-- something to this effect, but now that you have the file name,
-- do what you will...
do shell script "cd /Desktop/RunJar/; java -jar " & fileName
end tell
end repeat
end open
To add to Paul's answer
on open of finderObjects
repeat with currFile in finderObjects
-- ok, we have our current item. But it's an "alias": a Mac OS path
-- not a POSIX path
set unixPath to POSIX path of currFile
set base to do shell script "dirname " & unixPat
set fname to do shell script "basename " & unixPath
-- you could ask the Finder to give this to you too -- I'll use this way because
-- I'm guessing it's more familiar to you
do shell script "cd '" & base & "';" & " java -jar " & fname
end repeat
end open