Purely as an experiment, I’m trying to do something rather complex with AppleScript, mostly as an academic exercise more than anything, but I’m running into trouble. Here’s what’s happening.
First, I have a code library, called “ascr_code_library.scpt”, containing just one method:
on return_string_position(this_item, this_str, delim)
set old_delims to AppleScript's text item delimiters
set AppleScript's text item delimiters to delim
set this_list to text items of this_str
set found_pos to 0
repeat with i from 1 to the count of this_list
if item i of this_list is equal to this_item then set found_pos to i
end repeat
set AppleScript's text item delimiters to old_delims
return found_pos
end return_string_position
Then, I have this script, “test-2.scpt.” What it does is very simple, and pretty self-explanatory:
set scr_lib to load script (choose file with prompt "Please pick a library")
tell scr_lib
return_string_position("Who", "Who am I?", " ")
end tell
But what I get when I run the script and choose the file is the following error:
*“«data scpt4D617259332E303000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 . . . . . . . (etcetera, goes on fou five pages) . . . 1000101010CFADEDEAD» doesn’t understand the return_string_position message.”*
So where am I going wrong? It’s loading the script correctly, so far as I can tell. But where else could I be going wrong in such a simple script? I tried prefixing the method call with “my,” but that didn’t work either. Any ideas?
As mentioned in your previous question, I like this script better because it avoids delimiters and returns each instance.
on return_string_position(this_item, this_str)
set theWords to every word of this_str
set matchedWords to {}
repeat with i from 1 to count of theWords
set aWord to item i of theWords
if item i of theWords = this_item then set end of matchedWords to i
end repeat
return matchedWords
end return_string_position
return_string_position("very", "The coffee was very very very very very ... very hot.")
You can call the script like this:
run script file ((path to desktop as text) & "test 1.scpt") with parameters {"very", "The coffee was very very very very very ... very hot."}
Related
I would like to scan thru my Photo library (macOS 10.15.6, Photos App 5.0) and export selected photos' original file name to a text file. I have a simple script below as a starting point that doesn't properly convert the filename to readable text. I expect I need to execute some kind of 'convert to string' operation on the filename but I'm coming up empty on answers...
Any suggestions would be appreciated
code I'm currently using:
set myFile to open for access "/Users/ed/Desktop/testFile.txt" with write permission
write "file start\n" to myFile
tell application "Photos"
activate
set imageSel to (get selection)
if imageSel is {} then
error "Please select an image."
else
repeat with im in imageSel
write filename of im to myFile
write "\nnext photo\n" to myFile
end repeat
end if
end tell
write "file end\n" to myFile
close access myFile
My suggestion is to build the list of file names, then convert the list to paragraphs with text item delimiters and write the text to disk.
Further it's highly recommended to add reliable error handling to the write part.
tell application "Photos"
set imageSel to selection
if imageSel is {} then
error "Please select an image."
else
set theNames to {"file start"}
repeat with im in imageSel
set end of theNames to filename of im
end repeat
set end of theNames to "file end"
end if
end tell
set {TID, text item delimiters} to {text item delimiters, linefeed}
set theNames to theNames as text
set text item delimiters to TID
set testFile to POSIX path of (path to desktop) & "testFile.txt"
try
set fileDescriptor to open for access testFile with write permission
write theNames to fileDescriptor
close access fileDescriptor
on error
try
close testFile
end try
end try
I have a question and maybe someone can point me in the right direction.
I would like to be able to copy Text (mostly from "Get Info") and replace all the “.” with a space excluding the “.”before the file extension using AppleScript or Automator. I'd like to use this service when i right click and select the script or automator service.
E.G
Contraband.2012.DVDRip.htif-NYsIC.avi
will turn to
Contraband 2012 DVDRip htif-NYsIC.avi
I've search everywhere on this site and various places but I just cant seem to find what i need. I don’t know where to start writing this script. Is what i described even possible in apple script? I just need to be pointed in the right direction and I'll try and figure the rest out I'm just at a loss right now.
Thank's in advance.
You could use a Run Shell Script action like this:
for f; do
base=${f##*/}
[[ $base =~ .+\..+ ]] || continue
noext=${base%.*}
mv "$f" "${f%/*}/${noext//./ }.${base##*.}"
done
Set "Pass input" to "as arguments". ${f##*/} removes the longest */ pattern from the start of f and ${f%/*} removes the shortest /* pattern from the end of f.
You could also use a Run AppleScript action like this:
on run {input}
repeat with f in input
set text item delimiters to "."
tell application "Finder"
set ti to text items of (get name of (f as alias))
if number of ti > 2 then
set AppleScript's text item delimiters to " "
set name of (f as alias) to (items 1 thru -2 of ti as text) & "." & item -1 of ti
end if
end tell
end repeat
end run
I have a folder containing about 5000 files with names like:
Invoice 10.1 (2012) (Digital) (4-Attachments).pdf
Carbon Copy - Invoice No 02 (2010) (2 Copies) (Filed).pdf
01.Reciept #04 (Scanned-Copy).doc
I want to rename these files by removing everything from the first bracket onwards, so they look like this:
Invoice 10.1.pdf
Carbon Copy - Invoice No 02.pdf
01.Reciept #04.doc
I have found lots of scripts that will remove the last x letters, but nothing that will crop from a particular character.
Ideally I would like to use Automator, but I'm guess this might too complex for it. Any ideas?
Try:
set xxx to (choose folder)
tell application "Finder"
set yyy to every paragraph of (do shell script "ls " & POSIX path of xxx)
repeat with i from 1 to count of yyy
set theName to item i of yyy
set name of (file theName of xxx) to (do shell script "echo " & quoted form of theName & " | sed s'/ (.*)//'")
end repeat
end tell
The code posted by #adayzone will work, but there is no need to use sed for this – plain AppleScript will do, using offset:
set fullString to "Invoice 10.1 (2012) (Digital) (4-Attachments).pdf"
set trimmedString to text 1 thru ((offset of "(" in fullString) - 1) of fullString
-- trim trailing spaces
repeat while trimmedString ends with " "
set trimmedString to text 1 thru -2 of trimmedString
end repeat
this returns “Invoice 10.1". To split the file name into the name and extension, and re-add the extension, you can use System Events’ Disk-File-Folder suite, which will provide the handy name extension property you can store and re-add after trimming the name.
Assuming you use some Automator action to get the files to be processed, the full processing workflow would be to add an AppleScript action after the file selection part with the following code:
repeat with theFile in (input as list)
tell application "System Events"
set theFileAsDiskItem to disk item ((theFile as alias) as text)
set theFileExtension to name extension of theFileAsDiskItem
set fullString to name of theFileAsDiskItem
-- <insert code shown above here>
set name of theFileAsDiskItem to trimmedString & "." & theFileExtension
end tell
end repeat
If you want your Automator workflow to process the files any further, you will also have to create a list of aliases to the renamed files and return that from the AppleScript action (instead of input, which, of course, is not valid anymore).
How do I find the name of an executing AppleScript?
REASON: I want to create a script that changes its behavior based on its filename. Something like:
if myname is "Joe" then ACTION1
else if myname is "Frank" then ACTION2
else ACTION3
The normal way to get the name is by using "name of me". However applescripts are run by applescript runner so when you use that on a script you get "Applescript Runner" as the name. If you compile your script as an application then "name of me" will work. The only way to get the script name is by getting its path and extracting the name. Something like this would thus work for scripts...
getMyName()
tell me to display dialog result
on getMyName()
set myPath to path to me as text
if myPath ends with ":" then
set n to -2
else
set n to -1
end if
set AppleScript's text item delimiters to ":"
set myName to text item n of myPath
if (myName contains ".") then
set AppleScript's text item delimiters to "."
set myName to text 1 thru text item -2 of myName
end if
set AppleScript's text item delimiters to ""
return myName
end getMyName
Here's a method that works for all of the following:
*.scpt files (compiled AppleScript files; run in AppleScript Editor or with osascript)
*.applescript files (uncompiled AppleScript files; run in AppleScript Editor or with osascript)
command-line scripts that directly contain AppleScript (marked as executable and starting with #!/usr/bin/env osascript):
*.app files created with AppleScript Editor
*.app files created with Automator that contain AppleScript actions
Note: By contrast, it does not work for the following:
OS X services created with Automator that contain AppleScript actions (special *.workflow files) - always reports 'WorkflowServiceRunner[.xpc]'
general-purpose *.workflow files created with Automator that contain ApplesScript actions and that are run with automator - always reports 'Automator Runner[.app]'
Get the name of the running script, including filename extension (.scpt, .app, or .applescript, as the case may be):
tell application "System Events" to set myname to get name of (path to me)
If you want to remove the filename extension with a single command, use the following, do shell script-based approach:
tell application "System Events" to set myname to do shell script "rawName=" & quoted form of (get name of (path to me)) & "; printf '%s' \"${rawName%.*}\""
Here's an all-AppleScript alternative that is more verbose (yet concise by AppleScript standards):
tell application "System Events"
set myname to name of (path to me)
set extension to name extension of (path to me)
end tell
if length of extension > 0 then
# Make sure that `text item delimiters` has its default value here.
set myname to items 1 through -(2 + (length of extension)) of myname as text
end if
Finally, here's a variation: a subroutine that you can call with set myname to getMyName():
on getMyName()
local myName, tidSaved
tell application "System Events"
set myAlias to path to me -- alias to the file/bundle of the running script
set myName to name of myAlias -- filename with extension, if any.
if name extension of myAlias is not "" then -- strip away extension
set {tidSaved, AppleScript's text item delimiters} to {AppleScript's text item delimiters, {""}}
set myName to items 1 through -(2 + (length of (get name extension of myAlias))) of myName as text
set AppleScript's text item delimiters to tidSaved
end if
end tell
return myName
end getMyName
An easier way to find out the base part of the path is using name of:
tell application "Finder"
set p to path to me
set nam to name of file p as text
end tell
Maybe this:
set appname to name of current application
I made this Applescript script to create symbolic links.
Appart from POSIX path of, how can I get the file name, without the path, of the dropped file?
on open filelist
repeat with i in filelist
do shell script "ln -s " & POSIX path of i & " /Users/me/Desktop/symlink"
end repeat
end open
PS: I know this expects many files to be dropped and tries to create many links with the same name, which gives an error. Actually I copied this example from a website and as I don't know almost anything about Applescript, I don't know how to do this for a single file, help on that would be appreciated too.
I'm not sure what precisely you're trying to do, but I have a guess. Is the idea that you want to take every file dropped on the script and create a symbolic link to each one on the Desktop? So if I drop ~/look/at/me and ~/an/example, you'll have ~/Desktop/me and ~/Desktop/example? If that's what you want, then you're in luck: ln -s <file1> <file2> ... <directory> does exactly that. (Edit: Although you have to watch out for the two-argument case.) Thus, your code could look like this:
-- EDITED: Added the conditional setting of `dest` to prevent errors in the
-- two-arguments-to-ln case (see my comment).
on quoted(f)
return quoted form of POSIX path of f
end quoted
on open filelist
if filelist is {} then return
set dest to missing value
if (count of filelist) is 1 then
tell application "System Events" to set n to the name of item 1 of filelist
set dest to (path to desktop as string) & n
else
set dest to path to desktop
end if
set cmd to "ln -s"
repeat with f in filelist & dest
set cmd to cmd & " " & quoted(f)
end repeat
do shell script cmd
end open
Note the use of quoted form of; it wraps its argument in single quotes so executing in in the shell won't do anything funny.
If you want to get at the name of the file for another reason, you don't need to call out to the Finder; you can use System Events instead:
tell application "System Events" to get name of myAlias
will return the name of the file stored in myAlias.
Edit: If you want to do something to a single file, it's pretty easy. Instead of using repeat to iterate over every file, just perform the same action on the first file, accessed by item 1 of theList. So in this case, you might want something like this:
-- EDITED: Fixed the "linking a directory" case (see my comment).
on quoted(f)
return quoted form of POSIX path of f
end quoted
on open filelist
if filelist is {} then return
set f to item 1 of filelist
tell application "System Events" to set n to the name of f
do shell script "ln -s " & ¬
quoted(f) & " " & quoted((path to desktop as string) & n)
end open
It's pretty much the same, but we grab the first item in filelist and ignore the rest. Additionally, at the end, we display a dialog containing the name of the symlink, so the user knows what just happened.
As an example, you can work with the Finder instead of a shell script to get the name of a single file that is dropped on the script that is saved as an application. If you don't need the display dialog, you can remove it, but you have the file name as a variable to work with:
on open the_files
repeat with i from 1 to the count of the_files
tell application "Finder"
set myFileName to name of (item i of the_files)
end tell
display dialog "The file's name is " & myFileName
end repeat
end open