writing/reading a single variable in applescript - xcode

I'm just starting with applescript in xcode and currently have an app that asks for a folder location, then creates a folder structure.
on buttonClick_(sender)
set theLocation to choose folder with prompt "Where to save your project?"
tell application "Finder"
set newFolder to make new folder at theLocation with properties {name:(theTextField's stringValue() as string)}
set fontsFolder to make new folder at newFolder with properties {name:"fonts"}
set jpgFolder to make new folder at newFolder with properties {name:"jpg-pdf"}
set mainFolder to make new folder at newFolder with properties {name:"main"}
set printFolder to make new folder at mainFolder with properties {name:"• for printer"}
set refverFolder to make new folder at newFolder with properties {name:"ref_ver"}
set supportFolder to make new folder at newFolder with properties {name:"support"}
end tell
quit
end buttonClick_
Now I'm trying to have the app take "theLocation" folder alias and save it, so the next time the app launches it automatically chooses that folder as the save location without having to add it. I understand the logic that will go into it, but I can't figure out how to store/read information. I've tried tutorials on writing to the info.plist, but none of them have worked. Am I missing a basic piece of info on how applescript works?
Thanks
** Edit
script New_ProjectAppDelegate
property parent : class "NSObject"
property theTextField : missing value
property theLocation : ""
on applicationWillFinishLaunching_(aNotification)
tell standardUserDefaults() of current application's NSUserDefaults
registerDefaults_({theLocation:theLocation}) -- register the starting user default key:value items
set theLocation to objectForKey_("theLocation") as text -- read any previously saved items (which will update the values)
end tell
end applicationWillFinishLaunching_
on buttonClick_(sender)
if theLocation is "" then
set theLocation to choose folder with prompt "Where to save your project?"
tell standardUserDefaults() of current application's NSUserDefaults
setObject_forKey_(theLocation, "theLocation") -- update the default items
end tell
else
set theLocation to theLocation as text
--display dialog theLocation as text
end if
tell application "Finder"
set newFolder to make new folder at theLocation with properties {name:(theTextField's stringValue() as string)}
set fontsFolder to make new folder at newFolder with properties {name:"fonts"}
set jpgFolder to make new folder at newFolder with properties {name:"jpg-pdf"}
set mainFolder to make new folder at newFolder with properties {name:"main"}
set printFolder to make new folder at mainFolder with properties {name:"• for printer"}
set refverFolder to make new folder at newFolder with properties {name:"ref_ver"}
set supportFolder to make new folder at newFolder with properties {name:"support"}
end tell
quit
end buttonClick_
on applicationShouldTerminate_(sender)
tell standardUserDefaults() of current application's NSUserDefaults
setObject_forKey_(theLocation, "theLocation") -- update the default items
end tell
return current application's NSTerminateNow
end applicationShouldTerminate_
end script

Properties are not persistent in Xcode scripts, but you can utilize the user defaults system. To use the defaults, you register some initial values when your application starts up, then read from the defaults (which will overwrite the registered values if they have been saved before), and when your application quits save the new values - for example:
property theLocation : "" -- this will be the (text) folder path
on applicationWillFinishLaunching_(aNotification)
tell standardUserDefaults() of current application's NSUserDefaults
registerDefaults_({theLocation:theLocation}) -- register the starting user default key:value items
set theLocation to objectForKey_("theLocation") as text -- read any previously saved items (which will update the values)
end tell
-- other initialization stuff
end applicationWillFinishLaunching_
on buttonClick_(sender)
if theLocation is "" then
set theLocation to choose folder with prompt "Where to save your project?"
set theLocation to theLocation as text
end if
-- display dialog theLocation
tell application "Finder"
-- create folder structure
end tell
quit
end buttonClick_
on applicationShouldTerminate_(sender)
tell standardUserDefaults() of current application's NSUserDefaults
setObject_forKey_(theLocation, "theLocation") -- update the default items
end tell
return current application's NSTerminateNow
end applicationShouldTerminate_

You can define a property at the beginning of your script, which allows you to store information even after the script quits...
property theLocation : null
if theLocation is null then set theLocation to (choose folder with prompt "Where to save your project?"
...
The script will store the alias in "theLocation" for future use. However, saving or recompiling the script will reset the property back to its original value.

Related

AppleScript : How to get files in folder without hidden files?

I actually have two questions.
How to exclude hidden files like .DS_STORE, Icon when I try to get files in folder ?
I've tried "without invisibles" but it seems not working.
How to set my var the_new_folder as an existing folder if already exists ?
Thanks for answers.
My code:
--
-- Get all files in a selected folder
-- For each file, create a folder with the same name and put the file in
--
tell application "Finder"
set the_path to choose folder with prompt "Choose your folder..."
my file_to_folder(the_path)
end tell
on file_to_folder(the_folder)
tell application "Finder"
-- HELP NEEDED HERE
-- HOW TO EXCLUDE HIDDEN FILES (Like Icon, .DS_STORE, etc)
set the_files to files of the_folder
repeat with the_file in the_files
-- Exclude folder in selection
if kind of the_file is not "Folder" then
set the_path to container of the_file
set the_file_ext to name extension of the_file
-- Remove extension of the file name
set the_file_name to name of the_file as string
set the_file_name to text 1 thru ((offset of the_file_ext in (the_file_name)) - 2) of the_file_name
-- Make the new folder with the file name
try
set the_new_folder to make new folder at the_path with properties {name:the_file_name}
on error
-- HELP NEEDED HERE
-- HOW TO SET the_new_folder AS THE EXISTING FOLDER
end try
-- Move the file in the new folder
move the_file to the_new_folder
end if
end repeat
end tell
end file_to_folder
tell application "Finder"
(display dialog ("It's done!") buttons {"Perfect!"})
end tell
Using the System Events context instead of Finder:
bypasses the problem with the AppleShowAllFiles preference[1]
is much faster in general.
Using the visible property of file / folder objects in the System Events context allows you to predictably determine either all items, including hidden ones (by default), or only the visible ones (with whose visible is true):
# Sample input path.
set the_path to POSIX path of (path to home folder)
tell application "System Events"
set allVisibleFiles to files of folder the_path whose visible is true
end tell
Simply omit whose visible is true to include hidden files too.
The code for either referencing a preexisting folder or creating it on demand is essentially the same as in the Finder context:
# Sample input path.
set the_path to POSIX path of (path to home folder)
# Sample subfolder name
set the_subfolder_name to "subfolder"
tell application "System Events"
if folder (the_path & the_subfolder_name) exists then
set subfolder to folder (the_path & the_subfolder_name)
else
set subfolder to make new folder at folder the_path ¬
with properties {name: the_subfolder_name}
end if
end tell
[1] In order to predictably exclude hidden items, a Finder-based solution is not only cumbersome but has massive side effects:
You need to determine the current state of the the AppleShowAllFiles preference (defaults read com.apple.Finder AppleShowAllFiles),
then turn it off.
then kill Finder to make the change take effect (it restarts automatically) - this will be visually disruptive
then, after your code has run, restore it to its previous value.
then kill Finder again so that the restored value takes effect again.
I believe that your first question is not a problem. Your code works fine for me.
As for the second issue, the simplest method is to use the text representation of the_path, and simply build the new folder, and see if it already exists:
set the_path_Text to (the_path as text)
set try_Path to the_path_Text & the_file_name
if (folder try_Path) exists then
set the_new_folder to (folder try_Path)
else
set the_new_folder to make new folder at the_path with properties {name:the_file_name}
end if
If you are truly having difficulty with the first code section, please post a new question with more details, such as a copy of the Result section of the Script.
Thank you to all of you ! #mklement0 #craig-smith
You will find below the corrected code with your help!
If I share this code, you want to be cited for thanks?
--
-- Get all files in a selected folder
-- For each file, create a folder with the same name and put the file in
--
-- Get user folder
set the_path to choose folder with prompt "Choose your folder..."
my file_to_folder(the_path)
on file_to_folder(the_folder)
tell application "System Events"
-- Get all files without hidden
set the_files to files of the_folder whose visible is true
repeat with the_file in the_files
-- Remove extension of the file name
set the_file_ext to name extension of the_file
set the_file_name to name of the_file as string
set the_file_name to text 1 thru ((offset of the_file_ext in (the_file_name)) - 2) of the_file_name
-- Make a new folder or get the existing
set the_path to POSIX path of the_folder
if folder (the_path & the_file_name) exists then
set the_new_folder to folder (the_path & the_file_name)
else
set the_new_folder to make new folder at folder the_path with properties {name:the_file_name}
end if
-- Move the file to the new folder
move the_file to the_new_folder
end repeat
end tell
end file_to_folder
-- Ending dialog
display dialog ("It's done!") buttons {"Perfect!"}

Applescript - New file SHORTEST WAY

so where this question was all about was just that I forgot to change new file to new folder. (Because I just copy, pasted the code a few times.)
Regarding to the answer of vadian, here is the new code (edited):
property rustItems : {"Render.plist", "KleurInstellingen.txt", "Vrienden.txt", "Vijanden.txt", "Rust-Python-Embed.py", ¬
"Std__PATH.plist", "CargoRun.sett", "Rust-Package.fix", "Rust-Package-Auto.app", ¬
"Rust-PKG.pkg", "Project-Layout.jar", "Run-EXP.gib", "Radar.jar"}
property displayItems : {"Commons-io-2.4.jar", "commons-io-2.4.jar.sha", "Lastlog.log.gz", "Lastlog2.log.gz", ¬
"windows.pkg", "ModuleSettings.pkg", "ModuleStates.pkg", "ColorBinds.pkg", "ModsReturn.pkg", "Textures_1.png", "Textures_2.png", "Textures_3.png"}
property jortpepeItems : {"Rust.class", "Rust$1.class"}
property utilityItems : {"Layout.class", "XYZ__Layout.class"}
property managerItems : {"Restrictions.class", "MAX__DELAY.class"}
property listenerItems : {"OtherEvents.class", "PlayerEvents.class", "PlayerEvents$1.class", ¬
"PlayerChat.class", "PlayerChat$1.class"}
set chosenfolder to choose folder with prompt "Choose the Game folder to install the mods."
tell application "Finder"
if exists folder "Rust$1" of chosenfolder then delete folder "Rust$1" of chosenfolder
set modsFolder to make new folder at chosenfolder with properties {name:"Rust$1"}
repeat with anItem in rustItems
make new file at modsFolder with properties {name:anItem}
end repeat
set displayFolder to make new folder at modsFolder with properties {name:"Display"}
repeat with anItem in displayItems
make new file at displayFolder with properties {name:anItem}
end repeat
set jortpepeFolder to make new folder at modsFolder with properties {name:"jortpepe"}
repeat with anItem in jortpepeItems
make new file at jortpepeFolder with properties {name:anItem}
end repeat
set utilityFolder to make new folder at jortpepeFolder with properties {name:"Utilities"}
set managerFolder to make new folder at jortpepeFolder with properties {name:"Managers"}
set listenerFolder to make new folder at jortpepeFolder with properties {name:"Listeners"}
repeat with anItem in utilityItems
make new file at utilityFolder with properties {name:anItem}
end repeat
repeat with anItem in managerItems
make new file at managerFolder with properties {name:anItem}
end repeat
repeat with anItem in listenerItems
make new file at listenerFolder with properties {name:anItem}
end repeat
end tell
end
Thanks for reading.
Jort
PS: If you know another file extension I can add like .class .txt .pkg etc. then please give a comment to this question with that other file extension. (Because I still want a bigger fake library to be generated and with real existing file names it looks better :P)
Not really an answer, but an improvement.
This is a shorter version of your script using lists and repeat loops. Instead of an error branch repeating the whole code to create the structure it checks if the folder mods exists and delete it if necessary before creating the items.
property modsItems : {"Render.plist", "KleurInstellingen.txt", "Vrienden.txt", "Vijanden.txt", "Rust-Python-Embed.pyth", ¬
"Std__PATH.plist", "CargoRun.sett", "Rust-Package.fix", "Rust-Package-Auto.app", ¬
"Rust-PKG.pkg", "Project-Layout.jar", "Run-EXP.gib", "Downloaded.txt", "Enttree.jar", "Radar.jar"}
property displayItems : {"Commons-io-2.4.jar", "commons-io-2.4.jar.sha", "Lastlog.log.gz", "Lastlog2.log.gz", ¬
"windows.pkg", "ModuleSettings.pkg", "ModuleStates.pkg", "ColorBinds.pkg", "ModsReturn.pkg", "Textures_1.png", "Textures_2.png", "Textures_3.png"}
property jortpepeItems : {"Rust.class", "Rust$1.class"}
property utilityItems : {"Layout.class", "XYZ__Layout.class"}
property managerItems : {"Restrictions.class", "MAX__DELAY.class"}
property listenerItems : {"OtherEvents.class", "PlayerEvents.class", "PlayerEvents$1.class", ¬
"PlayerChat.class", "PlayerChat$1.class"}
set chosenfolder to choose folder with prompt "Choose the Game folder to install the mods."
tell application "Finder"
if exists folder "mods" of chosenfolder then delete folder "mods" of chosenfolder
set modsFolder to make new folder at chosenfolder with properties {name:"mods"}
repeat with anItem in modsItems
make new file at modsFolder with properties {name:anItem}
end repeat
set displayFolder to make new folder at modsFolder with properties {name:"Display"}
repeat with anItem in displayItems
make new file at displayFolder with properties {name:anItem}
end repeat
set jortpepeFolder to make new folder at modsFolder with properties {name:"jortpepe"}
repeat with anItem in jortpepeItems
make new file at jortpepeFolder with properties {name:anItem}
end repeat
set utilityFolder to make new folder at jortpepeFolder with properties {name:"Utilities"}
set managerFolder to make new folder at jortpepeFolder with properties {name:"Managers"}
set listenerFolder to make new folder at jortpepeFolder with properties {name:"Listeners"}
repeat with anItem in utilityItems
make new file at utilityFolder with properties {name:anItem}
end repeat
repeat with anItem in managerItems
make new file at managerFolder with properties {name:anItem}
end repeat
repeat with anItem in listenerItems
make new file at listenerFolder with properties {name:anItem}
end repeat
end tell
I already got the answer. In the script you'll see this code:
set thisfolder6 to make new file at thisfolder3 with properties {name:"Listeners"}
And I forgot to change the new file to new folder (I just did copy, paste, copy, paste, etc.)
So now the fixed code is:
set thisfolder6 to make new folder at thisfolder3 with properties {name:"Listeners"}
(I also changed this for the other rows)

Change icon of folder with AppleScript?

i've create an AppleScript very helpful to me and i wish if it is possible to automatically change the folder icon.
This script is very simple, it create one folder, then create one empty text file in the same folder.
Here is the script:
tell application "Finder"
set newfolder to make new folder with properties {name:My Folder}
make new file at newfolder with properties {name:"read_me.txt"}
end tell
Is it possible to automatically change the folder icon?
(I own my custom folder icon (.icns) in the same folder as the script, of course)
Heres a solution that uses a command line utility "seticon" found in this package: https://github.com/vasi/osxutils
It works on the assumption your script, icns file and new folder are all in the same directory.
tell application "Finder"
set parent_path to ((the container of the (path to me)) as text)
set target_folder_path to quoted form of POSIX path of (parent_path & "my folder")
set icon_path to quoted form of POSIX path of (parent_path & "icon.icns")
do shell script "/usr/local/bin/seticon -d " & icon_path & " " & target_folder_path
end tell
My Solution in 2021, using SF-Symbols
-- Help
-- folder_path : The folder whose icons will be changed (multiple selection in Finder possible)
-- icon_path : The Icon path
-- archiv_path : The Icon path for a folder named "Archiv"
-- Presets here as used by me
property folder_path : "/Users/ronny/Desktop/osxutils-master"
property icon_path : "/Volumes/Development/Developer/Xcode/LibPool/Icons/Folder.icns"
property archiv_path : "/Volumes/Development/Developer/Xcode/LibPool/Icons/Archiv.icns"
-- Frameworks and Additions
use framework "Foundation"
use framework "AppKit"
use scripting additions
-- Create list (array) with selected items
-- Be carefull, every icon will be changed
tell application "Finder"
set theListe to selection as list
end tell
repeat with i in theListe
set aName to name of i
log (aName)
set destPath to POSIX path of (i as text)
if aName is equal to "Archiv" then
set sourcePath to archiv_path
else
set sourcePath to icon_path
end if
set imageData to (current application's NSImage's alloc()'s initWithContentsOfFile:sourcePath)
(current application's NSWorkspace's sharedWorkspace()'s setIcon:imageData forFile:destPath options:2)
end repeat

Create Folders Applescript

I have an Applescript that I use to create job folders. The Applescript asks for the project name and the location where the folder will be stored. After inputting the job name and folder location, the script creates the main folder and four subfolders.
Now I would like the script to create numbered subfolders within one of the current subfolders, with a prompt that asks the user how many folders to create. Is that possible?
tell application "Finder"
set JobName to text returned of (display dialog "Please enter Job Name:" default answer "Job_Name")
set loc to choose folder "Choose Parent Folder Location"
set newfoldername to JobName
set newfo to make new folder at loc with properties {name:newfoldername}
make new folder at newfo with properties {name:"Job Materials"}
make new folder at newfo with properties {name:"Previews"}
make new folder at newfo with properties {name:"PSDs"}
make new folder at newfo with properties {name:"VX"}
end tell
set JobName to text returned of (display dialog "Please enter Job Name:" default answer "Job_Name")
set loc to choose folder "Choose Parent Folder Location"
tell application "Finder"
set newfo to make new folder at loc with properties {name:JobName}
make new folder at newfo with properties {name:"Job Materials"}
make new folder at newfo with properties {name:"Previews"}
set targetFolder to make new folder at newfo with properties {name:"PSDs"}
make new folder at newfo with properties {name:"VX"}
end tell
repeat
set subCount to text returned of (display dialog "How many subfolders?" default answer 3)
try
if subCount ≠ "" then
subCount as integer
exit repeat
end if
end try
end repeat
repeat with i from 1 to subCount
tell application "Finder" to make new folder at targetFolder with properties {name:"Subfolder " & i}
end repeat

Applescript: make new folder structure if it doesn't exist

I've been searching through message boards trying to figure out how to execute this script. Essentially the goal is to be able to run this script while inside a folder and if certain folders do not exist, these folders would then be created. If they do already exist, nothing happens. Here's what I've cobbled together so far:
property archivesFolder : "Archives"
property imagesFolder : "Images"
property proofreadFolder : "Proofreading"
property proofFolder : "Proofs"
property sourceFolder : "Source"
try
tell application "Finder" to set theLocation to (folder of the front window as alias)
end try
tell application "Finder"
if (exists folder archivesFolder) then
(* do nothing *)
else
make new folder at theLocation with properties {name:archivesFolder}
end if
if (exists folder imagesFolder) then
(* do nothing *)
else
make new folder at theLocation with properties {name:imagesFolder}
end if
if (exists folder proofreadFolder) then
(* do nothing *)
else
make new folder at theLocation with properties {name:proofreadFolder}
end if
if (exists folder proofFolder) then
(* do nothing *)
else
make new folder at theLocation with properties {name:proofFolder}
end if
if (exists folder sourceFolder) then
(* do nothing *)
else
make new folder at theLocation with properties {name:sourceFolder}
end if
end tell
What am I doing wrong ? (forgive my n00b code formatting, at work and can't figure out how to create code blocks) Also, is it possible to this not just on the front window, but on a folder that is just selected? Any help given would be awesome.
I suggest two options (to run the script):
Option 1: Take that code (assuming it does what you plan), and save it as an application (with Script Editor).
Then, just drag that application to your window toolbar (you need to have the toolbar visible). To do that, hold the command key while dragging.
Option 2: Use Butler: http://manytricks.com/butler/
(there is a free version, I don't know your OSX version).
It allows you to define system-wide shortcut keys for applescript scripts.
Create a smart item (applescript); paste the code there, and in the name of the script add the shortcut keys: example: create folder here ⇧⌥⌘N
EDIT:
According to your comment, I understand your problem and I can tell you that you were missing the path (the current folder, in your case theLocation)
So, in every case of if (exists folder archivesFolder) then you need to add the of theLocation like this: if not (exists folder archivesFolder of theLocation) then
Finally, knowing that you won't do any thing if the folder exists, just test the false case.
I tested this code and am posting it here:
property archivesFolder : "Archives"
property imagesFolder : "Images"
property proofreadFolder : "Proofreading"
property proofFolder : "Proofs"
property sourceFolder : "Source"
try
tell application "Finder" to set theLocation to (folder of the front window as alias)
end try
tell application "Finder"
if not (exists folder archivesFolder of theLocation) then
make new folder at theLocation with properties {name:archivesFolder}
end if
if not (exists folder imagesFolder of theLocation) then
make new folder at theLocation with properties {name:imagesFolder}
end if
if not (exists folder proofreadFolder of theLocation) then
make new folder at theLocation with properties {name:proofreadFolder}
end if
if not (exists folder proofFolder of theLocation) then
make new folder at theLocation with properties {name:proofFolder}
end if
if not (exists folder sourceFolder of theLocation) then
make new folder at theLocation with properties {name:sourceFolder}
end if
end tell
You can also use a shell script with mkdir, since the option to create intermediate folders won't error if the folder already exists.
# define a list of folders - items will need to be quoted if they contain spaces, etc.
property theFolders : {"Archives", "Images", "ProofReading", "Proofs", "Source"} -- can also nest, e.g. "Inside/One"
try
tell application "Finder" to set targetFolder to (target of the front window) as alias
on error -- no window
set targetFolder to (choose folder)
end try
# build a parameter string from the folder list
set {tempTID, AppleScript's text item delimiters} to {AppleScript's text item delimiters, space}
set {theFolders, AppleScript's text item delimiters} to {theFolders as text, tempTID}
do shell script "cd " & quoted form of POSIX path of targetFolder & "; mkdir -p " & theFolders
Try this:
tell application "Finder"
set theLocation to (target of front window) as string
set folderNames to {"archivesFolder", "imagesFolder", "proofreadFolder", "proofFolder", "sourceFolder"}
repeat with theFolder in folderNames
try
make new folder at theLocation with properties {name:"" & theFolder & ""}
end try
end repeat
end tell
This is a script I did to sort a bunch of medical files into subfolders based on the date of service (explaining the "text 5 thru 14" in the script; the files are named according to a pattern so the script can extract the date of service from the filename). Rather than check if the folder already exists, I just put the make folder instruction in a try block; if the folder already exists, the 'try' fails, but the script continues under the assumption that the folder already exists. Using the 'text' item instead of 'character' returns the extracted string as a single string and not as an array of characters that have to be converted back into a string.
tell application "Finder"
set theDirectory to "Internal Disk:Users:steven:Documents:Vondalee:Medical"
set theFiles to every file in folder theDirectory whose name extension is "pdf"
repeat with eachFile in theFiles
set theFileName to the name of eachFile
set theFolder to text 5 thru 14 of theFileName
try
make new folder at theDirectory with properties {name:theFolder}
end try
move eachFile to folder theFolder of folder theDirectory
end repeat
end tell

Resources