AppleScript and Shell Scripting

Terminal
Terminal | Source

Shell Scripts and the Terminal Application. Among the most neglected (and feared) areas of Mac OS and yet one of the most powerful, is Shell Scripting. While most of us who write scripts with AppleScript will never do a lot of scripting directly with UNIX through Terminal, there are still some scripts that can be run through AppleScript that can make it all the more powerful and efficient !

Mdfind Search by Document Name or Content

As the title implies, this is a shell script that shows an example of how to use shell scripting to search for files based upon a given keyword in their document name or optionally, based upon common content. It then, brings up a list to choose which document (or documents) you want to open.

it uses kMDItemDisplayName from mdfind to locate files based on document name and kMDItemTextContent to search for files with content matches. The option 'quoted form of' is necessary to indicate to the shell that the string searchText is, in fact, a string.

try
	set searchType to button returned of (display dialog "Search by document name or content ?" buttons {"Cancel", "Name", "Content"} default button 3 with title "Choose a search criteria" with icon 1)
	set searchText to text returned of (display dialog "Enter text for search:" default answer "" buttons {"Cancel", "Search"} default button 2 with icon 1 with title "File Search")
	--This is for an exact content search:
	if searchType = "Content" then
		set choosePrompt to "Files found with content '"
		set matchText to paragraphs of (do shell script "mdfind \"kMDItemTextContent == " & quoted form of searchText & "\"")
		--This is for an exact match for a document or folder name:
	else if searchType = "Name" then
		set choosePrompt to "Files found with names containing '"
		set matchText to paragraphs of (do shell script "mdfind \"kMDItemDisplayName == " & quoted form of searchText & "\"")
	end if
	
	if matchText ≠ {} then
		set targetMatch to (choose from list matchText with prompt choosePrompt & searchText & "':" with title "Search Result: " & searchText OK button name "Open" with multiple selections allowed) as string
		if targetMatch ≠ "false" then tell application "Finder" to open (POSIX file targetMatch) as alias
	else
		display alert "Not Found" message "The text '" & searchText & "' was not found in the current directory" buttons "OK" default button 1 giving up after 10 as warning
	end if
on error
	return
end try

Filter Folder Items by Date

This is a script, which takes user information to find files that have been modified within a specified time period, excluding a specified file type and displays the found files in a choose from list so you can select a file to open.

This can be very useful when you need to filter out files to see only the relevant files modified within a specific time period. So it serves as a sort of 'recent items' script when you know that you need to locate a file in a given directory, but you may not remember for sure what the name of the file is.

try
	set saveDelimiters to text item delimiters of AppleScript
	set documentsDirectory to POSIX path of (choose folder with prompt "Choose a source folder to search")
	set timePeriods to {"1 day", "3 days", "7 days", "15 days", "30 days"}
	set timePeriod to (choose from list timePeriods with prompt "Show files modified within:" with title "Filter Files by Date" default items "30 days" OK button name "Filter") as string
	set timePeriodName to timePeriod
	set text item delimiters of AppleScript to space
	set timePeriod to ("-" & (text item 1 of timePeriod) & "d") as string
	set text item delimiters of AppleScript to return
	set excludeTypes to {".txt", ".rtf", ".cwk", ".doc"}
	set excludeType to (choose from list excludeTypes with prompt "Choose file type to exclude in search:" with title "Exclude File Type" default items ".txt" OK button name "Exclude") as string
	set excludeType to ("'*" & excludeType & "'") as string
	set recentFiles to text items of (do shell script "/usr/bin/find " & quoted form of documentsDirectory & " -type f ! -name " & excludeType & " -mtime " & timePeriod & " -print ") as list
	set file2Open to (choose from list recentFiles with prompt "Files found which have been modified in last " & timePeriodName & "." with title timePeriodName default items (text item 1 of recentFiles) OK button name "Open") as string
	open file2Open
	set text item delimiters of AppleScript to saveDelimiters
on error
	display alert "User Cancelled" message "No document was chosen from directory " & documentsDirectory & "." buttons {"OK"} default button 1 as warning
	return
end try

Shell Open Files by Extension

Use this script to find all files in your current user domain of a specified file type. The magic of this is in the parsed shell script in line 10 and the complicated coercion of the open command in line 16.

This script comes in handy when you need to find s specific file of a specific type that may be lost down in several embedded folders. It could also be modified to find files that have something in common in their file names such as 'invoices'

i.e.: set shellScript to ("find ~/ -type f -name " & quoted form of "*Invoices")

tell application "Finder"
	activate
	try
		set saveDelimiters to text item delimiters of AppleScript
		set extensionList to {"cwk", "doc", "docx", "fp5", "fp7", "jpg", "pdf", "rtf", "scpt", "txt"}
		set extensionSuffix to (choose from list extensionList with prompt "Choose an extension suffix for search:" default items (text item 1 of extensionList) with title "File Extensions" OK button name "Find All")
		if extensionSuffix = false then error
		display alert "Extension " & extensionSuffix message "Searching..." & return & "...this may take some time..." giving up after 6 as informational
		--eg: search for files of type "doc" in the current users directory:
		set shellScript to ("find ~/ -type f -name " & quoted form of ("*." & extensionSuffix))
		set shellResult to {}
		set text item delimiters of AppleScript to return
		set shellResult to text items of (do shell script shellScript)
		set targetFile to (choose from list shellResult with prompt "Choose a file of type ." & extensionSuffix & " extension to open:" default items (text item 1 of shellResult) with title "File Type '" & extensionSuffix & "'" OK button name "Open") as text
		if targetFile = false then error
		open (POSIX file (contents of targetFile) as alias)
		set text item delimiters of AppleScript to saveDelimiters
	on error theError number theNumber
		if extensionSuffix = false or targetFile = false then
			set text item delimiters of AppleScript to saveDelimiters
			return -- user cancelled
		else
			display alert theNumber message theError
		end if
	end try
end tell

Using 'mdfind' to Locate Specific File Types

This script shows how to extract specific file types using the shell. Note in the third script line, that I call for the quoted form of the folder path before initiating the shell script. This important to deal with potential spaces in folder name, which would lead to an error.


Also note the line (near the end of the script):

set targetScpt to (((targetScpt as POSIX file) as alias) as string)


This is a very important coercion that is necessary for proper handling by the Finder.

set theFolder to (choose folder with prompt "Choose a folder to examine:")
--result > alias "Macintosh HD:Users:currentUser:Desktop:AppleScripts:"
set folderName to (theFolder as string)
--result > "Macintosh HD:Users:currentUser:Desktop:AppleScripts:"
set folderPOSIX to quoted form of POSIX path of theFolder
--result > ""'/Users/currentUser/Desktop/AppleScripts/'"
set theAliases to paragraphs of (do shell script "mdfind -onlyin " & folderPOSIX & " 'kMDItemKind == \"Alias\"'") --a list of files of type 'alias' notice double '=' signs
set text item delimiters of AppleScript to {ASCII character 13} -- a return character
display dialog "Alias files found in folder: " & folderName & return & return & (text items of theAliases) --this shows the aliases found in the 'AppleScripts' folder as a dialog
set scriptFiles to paragraphs of (do shell script "mdfind -onlyin " & folderPOSIX & " 'kMDItemFSCreatorCode == \"ToyS\"'") --a list of files created in AppleScript ie 'scpt'
display dialog "AppleScript Script files found in folder: " & folderName & return & return & (text items of scriptFiles) --this shows the AppleScript files found in the 'AppleScripts' folder as a dialog
set targetScpt to (choose from list scriptFiles with prompt "Choose a file to open:" with title "AppleScript Script files found in folder: " & folderName OK button name "Open") --this shows the files as a list
set targetScpt to (((targetScpt as POSIX file) as alias) as string) 
--result >"Macintosh HD:Users:currentUser:Desktop:AppleScripts:Make New Picture Album.scpt"
tell application "Finder" to open document file targetScpt

Search and Open Word Document with 'mdfind''

This is a handy little script to find your Word Documents and display them in a 'choose from list' dialog sheet. On the surface, it appears that the mdfind is only searching for files of type doc, but, in fact, it finds both doc files and docx files.


After you choose a file, the Finder takes over and opens the chosen file.

try
	set saveDelimiters to text item delimiters of AppleScript
	set searchTerm to text returned of (display dialog "Enter a search term:" default answer "AppleScript" with title "Search for Microsoft Word Documents" buttons {"Cancel", "Search"} default button 2 with icon 1)
	set theDocs to (do shell script "mdfind searchTerm | grep \".doc\"")
	set text item delimiters of AppleScript to {ASCII character 13} -- a return character
	set targetFile to ((choose from list (text items of theDocs) as list with prompt "Choose a file to open:") as POSIX file) as alias
	set targetFile to (targetFile as string)
	tell application "Finder" to open document file targetFile
	set text item delimiters of AppleScript to saveDelimiters
on error
	return
end try

Sorting Text Items with Shell

While there are a couple of different options for sorting text items with AppleScript, with long lists of items, AppleScript can be really slow. Sending the data to the Shell for sorting and returning the result back to an AppleScript, on the other hand, is much more efficient.

Examine the script lines below and their results:

set saveDelimiters to text item delimiters of AppleScript
set cityList to {"Rome", "New York", "Berlin", "Paris", "Montréal", "Rio de Janiero"}
set text item delimiters of AppleScript to {ASCII character 10} -- this is a linefeed
set cityListString to (cityList as string)

--> result:
(*"Rome
New York
Berlin
Paris
Montréal
Rio de Janiero"*)

set sortedString to do shell script "echo " & quoted form of cityListString & " | sort -f"

--> result:
(*"Berlin
Montréal
New York
Paris
Rio de Janiero
Rome"*)

set cityParagraphs to (paragraphs of sortedString)

--> result: {"Berlin", "Montréal", "New York", "Paris", "Rio de Janiero", "Rome"}

set chooseCity to choose from list cityParagraphs with prompt "Which city would like to visit today ?"
display alert chooseCity message "That's a nice city to visit. Pack your bags !" as informational
set text item delimiters of AppleScript to saveDelimiters

Scripting Preview

Adding AppleScript to Preview For those of you who want to be able to script Preview by 'normal means' with AppleScript (i.e. without having to script through Terminal), you will find this script, which I found on the MacWorld site, very useful:

try
	tell application "Finder"
		set Preview_app to (application file id "com.apple.Preview") as alias
	end tell
	set plist_filepath to quoted form of ((POSIX path of Preview_app) & "Contents/Info")
	do shell script "defaults write " & plist_filepath & space & "NSAppleScriptEnabled -bool YES"
end try

The script line:

do shell script "defaults write " & plist_filepath & space & "NSAppleScriptEnabled -bool YES"


is the key to this. It writes to the data of Preview and to tell it to recognize AppleScript.

Or, if you really want to just do this directly from Terminal:

defaults write /Applications/Preview.app/Contents/Info NSAppleScriptEnabled -bool YES


For other tips, go to: http://www.macworld.com/

Creating a Calendar in TextEdit with Shell Script

This is sort of a fun script which gives you some idea of the power behind the UNIX side of Mac OS X. Impressive as this little bit of shell code is though, it only scratches the surface on what you can do combining the power of AppleScript with the shell:

display dialog "Choose a color for your calendar" buttons "OK" default button 1 with icon 1 with title "Calendar Color" giving up after 1
choose color default color {65535, 5786, 28421}
set calendarColor to the result
set defaultYear to year of (current date)
display dialog "Enter desired calendar year:" default answer defaultYear buttons {"Cancel", "Make Calendar"} default button 2
copy the result as list to {calendarYear, returnedButton}
if returnedButton = "Make Calendar" then
	set cmdResult to (do shell script "cal " & calendarYear)
	tell application "TextEdit"
		activate
		set yearCalendar to make new document with properties {text:cmdResult}
		set properties of text of yearCalendar to {size:12.0, color:calendarColor, font:"Monaco"}
		set bounds of window 1 to {0, 22, 612, 792}
	end tell
else
	try
	on error errorMsg number errorNumber
		set errorText to "Error: " & the errorNumber & ". " & errorMsg
		display dialog errorText buttons "OK" default button 1 with icon 0
		return errorText
	end try
end if

For correct formatting, the font you use must be a monospaced type such as: Andale Mono, Monaco, Courier or Courier New.

Creating Folder with Subfolders Using Shell

The Magic of the Mkdir Command

This is a script that triggers the shell to create a folder whose name you specify with subfolders. Although this could be done with regular AppleScripting, this is an example of where the shell really shines; the shell can do it a whole lot more easily than AppleScript alone.

try
	set mainFolder to text returned of (display dialog "Enter a name for the main folder:" default answer "Physics")
	set secondaryPrefix to text returned of (display dialog "Enter a name for the secondary folder:" default answer "Study")
	set posixDesktop to POSIX path of (path to desktop)
	set newFolders to "mkdir -p " & posixDesktop & "/" & mainFolder & "/" & secondaryPrefix & "'" & " '{1,2,3,4}/{Findings,Notes,Appendix}/"
	do shell script newFolders
	tell application "Finder"
		activate
		set desktopPath to (path to desktop) as alias
		set finderTarget to (desktopPath & mainFolder & ":" as string)
		select finderTarget
		open the selection
		display alert "Folder '" & mainFolder & "'" message "Folder creation complete." as informational
	end tell
on error
	display alert "Cancelled" message "Creation of folders has been aborted !" as warning
end try

This script queries the user for text entries for the variables: mainFolder and secondaryPrefix. The variable posixDesktop gets the POSIX path to the desktop folder which will be part of the string that is sent to Terminal to create the folders:

"mkdir -p " & posixDesktop & "/" & mainFolder & "/" & secondaryPrefix & "'" & " '{1,2,3,4}/{Findings,Notes,Appendix}/"

The variable secondaryPrefix is concatenated with the numbers {1,2,3,4} to create the four secondary folders.

© 2013 AppleScripter

More by this Author

  • AppleScript and FileMaker
    4

    Learning How to Write FileMaker Pro Scripts for Beginners. Free AppleScripts for those who are new. Many scripts are a mix of AppleScript and FileMaker.

  • Free AppleScript Code Examples
    1

    Write AppleScript Code,free AppleScripts of display dialog,display alert,choose from list,finder,choose file,choose file name,choose folder,choose application,choose color,Finder,TextEdit

  • More Advanced AppleScript Code
    0

    For those of you who still cannot get enough AppleScript to feed your fix, some more free applescript code,Finder,Microsoft Word,Pages,AppleWorks,PowerPoint,TextEdit,iTunes,POSIX paths,database events


Comments, Suggestions, Bugs ?

No comments yet.

    Sign in or sign up and post using a HubPages Network account.

    0 of 8192 characters used
    Post Comment

    No HTML is allowed in comments, but URLs will be hyperlinked. Comments are not for promoting your articles or other sites.


    Click to Rate This Article
    working