Currently I am trying to write the script which can determine the extensions that can open a chosen by the user application. I wrote following script, which works with some applications (like Calendar.app and Automator.app), and doesn't work with other apps (like Finder.app, Handbrake.app).
Can anyone help me to make my script universal? Or, maybe, someone know better solution than mine.
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
-- get posix path of chosen application
set applicationPosixPath to POSIX path of (path to (choose application))
-- coerce to NSURL
set theURL to current application's |NSURL|'s fileURLWithPath:applicationPosixPath
-- get chosen application's NSBundle
set theBundle to current application's NSBundle's bundleWithURL:theURL
-- get document types info
set CFBundleDocumentTypes to (theBundle's infoDictionary()'s objectForKey:"CFBundleDocumentTypes") as list
-- get the list of extensions the chosen application opens
set theExtensions to {}
repeat with anItem in CFBundleDocumentTypes
set end of theExtensions to item 1 of CFBundleTypeExtensions of anItem
end repeat
return theExtensions
OK,
I found what was the mistake. So, if legal filename extensions are indicated in the Info.plist file of the application bundle, then their list can be obtained as follows. If they are not specified, then the result will be an empty list:
-- script: Trying to get legal filename extensions to open with chosen app
-- written by KniazidisR, right now
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
-- get posix path of chosen application
set applicationPosixPath to POSIX path of (path to (choose application))
-- coerce to NSURL
set theURL to current application's |NSURL|'s fileURLWithPath:applicationPosixPath
-- get chosen application's NSBundle
set theBundle to current application's NSBundle's bundleWithURL:theURL
-- get document types info
set CFBundleDocumentTypes to (theBundle's infoDictionary()'s objectForKey:"CFBundleDocumentTypes")
set theExtensions to {}
repeat with theDictionary in CFBundleDocumentTypes
set adding to (theDictionary's objectForKey:"CFBundleTypeExtensions") as list
if adding does not contain {missing value} then set theExtensions to theExtensions & adding
end repeat
theExtensions
Related
I'm trying to find the folder which has been last modified. (Actually, I'm only interested in that folder and not an ordered list.) I'm getting an -10010 error.
tell application "Finder"
try
set latestFolder to item 1 of (sort (get name of folders of folder ("/Users/c64/Desktop" as POSIX file)) by creation date) as alias
set folderName to latestFolder's name
end try
end tell
If you're looking for the name of the last modified folder on the Desktop, then this will do it:
tell application "Finder"
set latestModifiedFolderName to name of item 1 of (sort every folder by modification date)
end tell
By the way, the AppleScript Dictionary for Finder does not contain terms POSIX file or POSIX path and when using e.g. POSIX file inside of a tell application "Finder" block, Finder will throw a non-fatal error if it can be coerced into an alias, otherwise it can throw a fatal error. That said, if you are dealing with a POSIX path, it's probably best to pass it to Finder as an alias, and I'd recommend coercing the POSIX path to an alias before passing it to Finder, e.g.:
set thisFolderPath to POSIX file "/Path/To/Some/Folder" as alias
tell application "Finder"
set latestModifiedFolderName to name of item 1 of (sort every folder of thisFolderPath by modification date)
end tell
Note: The example AppleScript code above is just that, and does not include any error handling as may be appropriate/needed/wanted, the onus is upon the user to add any error handling for any example code presented and or code written by the oneself.
Here's our situation:
We have a list of file names and/or full file paths (we can generate either)
The files in our list are all contained under one folder, but scattered across multiple sub-folders. (There are hundreds of items in our select list from thousands of possible files. Selecting manually isn't an option)
We've got the root folder open in list view and all sub-folders, sub-sub etc disclosure-opened (btw thanks to http://hints.macworld.com/article.php?story=20030218164922494 for the shortcut "command, option, control and shift when pressing the right arrow")
With all files visible under one window open we want to automatically select all the items in our file list so that they can then be dragged at once to an application.
I do not believe that with basic AppleScript one can programmatically select multiple items in Finder which span throughout different folders and subfolders within a given folder in one window. Maybe with Cocoa-AppleScript, don't know, however if Avid can open files from file aliases, then the following example AppleScript code is a viable option.
The example AppleScript code makes the following assumptions:
There is a plain text file containing the fully qualified POSIX pathnames of the target files to be processed with Avid and the name of the file is: List of Files to Process with Avid.txt
The name of the folder containing the aliases is: Aliases of Files to Process with Avid
The Desktop is used as the location in the filesystem that the aforementioned file and folder exists, to be processed by Avid.
Obviously these settings can be changed as needed/wanted, see the comments in the code.
Example AppleScript code:
-- # Set the value of the following three property variables:
-- #
-- # The value of 'thisLocation' is an colon-delimited path string, e.g. 'path to desktop as string' returns: "Macintosh HD:Users:me:Desktop:"
-- # NOTE: When not using 'path to (folder)' where 'folder' is a 'folder constant' , the special folder for which to return the path, the value should be in the form of an colon-delimited path string.
-- # See: https://developer.apple.com/library/content/documentation/AppleScript/Conceptual/AppleScriptLangGuide/reference/ASLR_cmds.html#//apple_ref/doc/uid/TP40000983-CH216-SW19
-- #
-- # The value of 'theListFilename' is the name of the plain text file containing the fully quilified pathnames of the target files to be opened in Avid.
-- # The value of 'theFolderName' is the name of the temporary folder the temporary aliases will be created in. This folder gets created new each run with new aliases.
-- #
-- # NOTE: For ease of use, as each run is presumed to be temporary to get that job run done, the location of the 'theListFilename' and 'theFolderName' are both in 'thisLocation'.
property thisLocation : (path to desktop as string)
property theListFilename : "List of Files to Process with Avid.txt"
property theFolderName : "Aliases of Files to Process with Avid"
-- # The remaining code is tokenized and should not need to be modified.
tell application "Finder"
if (exists thisLocation & theListFilename) then
tell current application to set theList to read alias (thisLocation & theListFilename)
else
display dialog "The file, \"" & theListFilename & "\", was not found at the expected location." buttons {"OK"} ¬
default button 1 with title "Missing File" with icon 0
return
end if
set theFolderPathname to thisLocation & theFolderName
if not (exists theFolderPathname) then
make new folder at thisLocation with properties {name:theFolderName}
else
move theFolderPathname to trash
make new folder at thisLocation with properties {name:theFolderName}
end if
repeat with i from 1 to length of theList
try
make new alias file at theFolderPathname to POSIX file (paragraph i of theList)
end try
end repeat
reveal theFolderPathname
activate
-- delay 1 -- # In necessary, uncomment and adjust value as appropriate.
select every item of alias theFolderPathname
end tell
In Script Editor, save this script and an application, e.g. Select Files to Process with Avid, and then run as needed after replacing the e.g. List of Files to Process with Avid.txt with the current set of target files to be processed with Avid.
The script does the following:
Checks to see the file e.g. List of Files to Process with Avid.txt exists and if not displays error message and exits.
Checks to see if the folder e.g. Aliases of Files to Process with Avid exist and if not creates it, and if it exists, moves it to the Trash and creates it anew, for the new run of target files to be processed.
Creates an alias of each file listed, as a fully qualified POSIX pathname, in the file e.g.: List of Files to Process with Avid.txt
Opens the folder, e.g. Select Files to Process with Avid, in Finder and selects the aliases.
You are now ready to drag and drop the selected aliases to Avid.
Note: This script assumes the fully qualified POSIX pathnames of the target files to be processes with Avid do not contain linefeeds, carriage returns and or null characters in their pathnames.
This works using the latest version of Sierra.
I was not able to figure out a way to selectively select files in folders with subfolders with subfolders etc. The only solution I was able to come up with was to create folder called “Aliases” and have AppleScript create alias files to all of the ”selected files” and store all of the aliases in the aliases folder. From there you can drag all of the files and drop them into your application as you desired
If you have a plain text file containing POSIX path filenames, each on a separate line like the example in this next image, this version will load the pathnames from the text file directly into the script. Just save this script as an application. You can drag text files directly onto the icon of the app because the code is set up to be a droplet
global theFile
property theInfo : missing value
property theName : missing value
property theList : {}
property theList2 : {}
property aliasFolder : (path to desktop as text) & "Aliases"
on open theFiles
set theInfo to info for theFiles
set theName to POSIX path of theFiles
getLinesofFileAsList(theName)
tell application "Finder"
if not (exists of alias aliasFolder) then
make new folder at (path to desktop as text) with properties {name:"Aliases"}
end if
delete every item of alias aliasFolder
end tell
repeat with i from 1 to count of theList
try
set theResult to POSIX file (item i of theList) as text
set end of theList2 to theResult
tell application "Finder"
set theAliases to make new alias file at aliasFolder to theResult
end tell
end try
end repeat
delay 0.5
tell application "Finder"
activate
delay 0.5
set hmmm to reveal aliasFolder
delay 0.5
set hmmm to select every item of alias aliasFolder
activate hmmm
end tell
end open
on getLinesofFileAsList(theName)
set theFile to theName
set theFile to POSIX path of theName
set theList to read POSIX file theFile as text
set saveTID to AppleScript's text item delimiters
set AppleScript's text item delimiters to linefeed
set theList to paragraphs of theList
if last item of theList is "" then
set theList to reverse of rest of reverse of theList
end if
set AppleScript's text item delimiters to saveTID
end getLinesofFileAsList
--on run
-- -- Handle the case where the script is launched without any dropped files
--end run
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!"}
i am creating an applescript to create a file with property list elements but without the .plist extension!
my issue is if i use a dialog to get the name of the file eg.
tell application "SystemUIServer"
display dialog "Enter filename :- " buttons {"Generate file"} default answer "Generate Keyfile"
set fileName to text returned of result
and create the file on the desktop like so
set text_file to (path to desktop)'s POSIX path & "" & quoted form of fileName & ".NEWextention"
finally i add elements to the .plist
tell application "System Events"
tell (make new property list file with properties {name:text_file})
make new property list item at end with properties {kind:string, name:"regName", value:"FOO"}
make new property list item at end with properties {kind:string, name:"regNumber", value:"BAR" as text}
end tell
end tell
end tell
however the file that is created is has '' when quoted from fileName and still has the .plist extention.
eg input :- myfile
output:- 'myfile'.NEWextention.plist
when i want
myfile.NEWextention
how can i achieve this in applescript?
any help would be greatly appreciated!
many thanks in advance.
below is the fixed code thanks to #McUsr
without his help i would have been at the same point for over 6 months of trial and error
tell application "SystemUIServer"
display dialog "Enter FileName :- " buttons {"Generate file"} default answer "Generate file"
set FileName to text returned of result
set text_file to (path to desktop folder as text) & FileName & ".plist"
set dateStamp to do shell script "date"
tell application "System Events"
tell (make new property list file with properties {name:text_file})
make new property list item at end with properties {kind:string, name:"Name", value:FileName}
make new property list item at end with properties {kind:string, name:"Date", value:dateStamp}
end tell
end tell
end tell
tell application "Finder"
set name extension of file text_file to "newExt"
end tell
You can make it happen afterwards you are done processing it with System Events, by Finder, (set name extension of file "Hfs:path:to:file:with:name.ext" to "new-ext").
But I am not sure if you can expect System Events to regard the file as a property list file, containing property list items afterwards. It is still worth a try though. :)
This is how you must change the name extension, as this don't work with System Events (name extension is a read only property).
tell application "Finder"
set mf to (path to desktop folder as text) & "labels.txt"
set name extension of file mf to "text"
end tell
Use the HFS path of the file, aka: Macintosh Hd:Users:You:path:file.ext, and not the posix path. And don't use quoted form of det path.
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