Out of pure frustration with not being able to have a key to conveniently make script files into executables, I built this crazy AppleScript. It will ask a user to select some file and then make a new copy of that file in executable format. I think it goes a little beyond just the chmod +x because the new executable will have the nice looking UNIX executable icon attached to it.
If the script doesn’t output an executable file right away, try opening that file with TextEdit, saving it, and then opening an information window from Finder (+i). It works most of the time but, since it’s horribly hackish, it does miss converting a file every so often.
The script should be added as an automator service and put on a hotkey to make it easily accessible! --this is kind of the whole reason for the script
set theExoticCharacters to {" ", "'", "\"", ";", ":", "*"} --expand this list if needed
set theNormalCharacters to {"\\ ", "\\'", "\\\"", "\\;", "\\:", "\\*"} --corrects characters for Terminal
tell application "Finder"
set the_file to choose file
set file_name to (name of the_file)
set file_name to my remove_extension(file_name)
set parent_fol to folder of the_file
set new_file to make new file at parent_fol with properties {name:file_name, kind:"Unix Executable File"}
end tell
set the_text to read the_file
set new_file to new_file as text
set the open_newFile to open for access new_file with write permission
write the_text to open_newFile
close access the open_newFile
set new_fileName to my renameFile(new_file)
set newest_fileName to my POXIFY_location(new_fileName)
do shell script "chmod u+x " & newest_fileName & ""
tell application "Finder"
open file new_file
tell application "System Events"
keystroke "s" using {command down}
keystroke "w" using {command down}
end tell
select file new_file
tell application "System Events"
keystroke "i" using {command down}
keystroke "w" using {command down}
tell process "Finder"
set frontmost to true
keystroke "w" using {command down}
end tell
end tell
end tell
------------------------------
on remove_extension(this_name)
if this_name contains "." then
set this_name to ¬
(the reverse of every character of this_name) as string
set x to the offset of "." in this_name
set this_name to (text (x + 1) thru -1 of this_name)
set this_name to (the reverse of every character of this_name) as string
end if
return this_name
end remove_extension
on POXIFY_location(this_name)
if this_name contains ":" then
set this_name to (every character of this_name) as string
set x to the offset of ":" in this_name
set this_name to (text (x + 1) thru -1 of this_name)
set this_name to (every character of this_name) as string
end if
set oldTID to AppleScript's text item delimiters
repeat with i from 1 to count of ":"
set AppleScript's text item delimiters to item i of ":"
set theTextBits to text items of this_name
set AppleScript's text item delimiters to item i of "/"
set this_name to theTextBits as text
end repeat
set AppleScript's text item delimiters to oldTID
return this_name
end POXIFY_location
on renameFile(theName)
global theExoticCharacters, theNormalCharacters
set oldTID to AppleScript's text item delimiters
repeat with i from 1 to count of theExoticCharacters
set AppleScript's text item delimiters to item i of theExoticCharacters
set theTextBits to text items of theName
set AppleScript's text item delimiters to item i of theNormalCharacters
set theName to theTextBits as text
end repeat
set AppleScript's text item delimiters to oldTID
return theName
end renameFile
This is a different take, for other purposes. Not as versatile as yours.
This works from within BBEdit (but just change it to “TextWrangler”), and I go to a long extent of not having to enter a localized file kind, god knows what the kind is in Portuguese for instance!
I’m confused as to why you’d need to reverse the string - twice. Can’t you get the offset then copy from S(1) to S(n) where S(n) is 1 character before the offset?
What am I missing?
Example:
display dialog remove_extension("filename.txt")
on remove_extension(this_name)
if this_name contains "." then
set x to the offset of "." in this_name
set this_name to (text (1) thru (x - 1)) of this_name
end if
return this_name
end remove_extension
A file names filename.txt.zip ? The file name is filename.txt and the extension is zip. Unlike bash, I mention this because of your name, AppleScript only has a one direction offset
EDIT: an example of what I meant:
removeExtension("filename.txt.zip")
on removeExtension(fileName)
do shell script "a=" & quoted form of fileName & ";echo ${a%.*}"
end removeExtension
EDIT2:
Don’t use POXIFY_location(this_name). It’s wrong to do that yourself, let the command POSIX path handle this:
set macintoshPath to "Macintosh HD:Users:you:Desktop:testfile.txt"
set posixPath to POSIX path of macintoshPath
Maybe someone is interested in this simple script:
(* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* DISCUSSION
* This script is designed as an addition to TextEdit.app to write shell script.
* It takes the string value from the fornt most document from TextEdit.app
* The string is stored in a file named shellRunner, located in the temporary folder
* The file's executable flag (with chmod) is set
* The new script file is executed and it's stdout and stderr are redirected to shellrunner_log
* shellrunner_log is located in the temporary folder next to the script
* The log file is also opened in Console.app after it's finished
*
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* USAGE: A small tutorial
* 1) Open/launch from your applications folder the application TextEdit.app
* 2) Write in the (front most) document 'echo "Hello World!"' (text between the single quotes)
* 3) Launch this script
*
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Revision history:
* 0.4: bash scripts containing more than the maximum allowed characters on the command line can be executed now
* 0.3.1: open the the log file now with console as identifier
* 0.3: Shows errors in the console as well and don't show up as an error in this script
* 0.2: Show result in the console
* 0.1: First working solution:
*
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Plans in future releases
* 1) Make it idiot proof: check if there is document open etc...
* 2) Create a property/flag where the results should be opened (script editor, console, terminal)
* 3) Create a dialog wheter you want to run or save the script
* 4) Check for the user privileges of the openend document
* 5) In addition to point 4: Ability to run the script as another user
* 6) preprocessing
*)
property creator : "DJ Bazzie Wazzie"
property version : 0.4
tell application "TextEdit"
set theSource to text of document 1
end tell
set execFile to (path to temporary items as text) & "shellRunner"
set execLogFile to (path to temporary items as text) & "shellrunner_log"
--0.4 do shell script "/bin/echo -n " & quoted form of theSource " & > quoted form of posix path of execfile
try
set descriptor to open for access file execFile with write permission
set eof of descriptor to 0
write theSource to descriptor as «class utf8»
close access descriptor
on error m
close access file execFile
return m
end try
do shell script "chmod u+x " & quoted form of POSIX path of execFile
--0.3: " > " has been replaced with " &> " to pass messages to stderr to console as well
do shell script quoted form of POSIX path of execFile & " &> " & quoted form of POSIX path of execLogFile
do shell script "open -a console " & quoted form of POSIX path of execLogFile
Didn’t know about that. That seems like a strange omission of [any] programming language. Makes for more clumsy code than is necessary. The OP’s solution makes more sense, now. I’ve only tinkered with Applescript. Does it have a strings library, or does everyone just roll their own? I’d definitely code a right_offset() and stick it in.
To your second part, if if it was that practical to code and use a right_offset() then everyone would have done it.
You’ll end up with something like this, which eats cycles, we usually do string handling by text item delimiters, which considers content more than position.
set m to "myfilename is long.txt.zip"
set rofs to right_offset for m by "."
set n to text 1 thru (rofs - 1) of m
-->"myfilename is long.txt"
to right_offset for sToSearch by sString
” McUsr made this handler and put into Public Domain without copyright!
” http://macscripter.net/edit.php?id=154775
local l1, l2, sofs, tofs, rofs
set l1 to length of sToSearch
if l1 = 0 then return 0
set l2 to length of sString
if l2 = 0 then return 0
set sofs to offset of (reverse of characters in sString as text) in (reverse of characters of sToSearch as text)
if sofs = 0 then return 0
set tofs to sofs + l2 - 1
set rofs to l1 - tofs + 1
return rofs
end right_offset
While I don’t disagree, it helps to understand that AppleScript was never designed as a general-purpose programming language, but rather as a simple user-friendly language to use to drive applications. Of course it’s used for tasks way beyond its initial remit, and you can argue that the original idea was somewhat short-sighted. (And of course you can argue that there’s been plenty of time to remedy things.) But it’s easier to understand what’s there if you also understand the intent.
Here is another idea, with respect to DJ Bazzie Wazzie`s.
This is really work in progress, this one filters the front text document through a shell command in BBEdit, and puts the result in an Output window. I know, you can just undo to bring the previous text back, but sometimes it is ok, to compare before and after, until you have the command right.
I found this at the address inside it, and modified it slightly, I am going to modify it further to work on a selection, when the moment is right.
-- https://groups.google.com/group/bbedit/tree/browse_frm/month/2009-07/688d7289fc320fb3?rnum=21&_done=%2Fgroup%2Fbbedit%2Fbrowse_frm%2Fmonth%2F2009-07%3F
property pPipeCommand : "sort | uniq"
on translate_line_breaks(str)
set AppleScript's text item delimiters to {ASCII character 13}
set _lines to every text item of str
set AppleScript's text item delimiters to {ASCII character 10}
set str to _lines as text
set AppleScript's text item delimiters to {}
return str
end translate_line_breaks
on run
tell application "BBEdit"
if not (exists text window 1) then
display alert "This script requires an open text window."
return
end if
if length of selection of text window 1 is 0 then
select text 1 of text window 1
end if
set _selectedText to selection of text window 1 as Unicode text
end tell
set _selectedText to translate_line_breaks(_selectedText)
set _tempFilePath to "/tmp/BBEditPipeTemp"
set _tempFile to open for access (POSIX file _tempFilePath) with write permission
set eof _tempFile to 0
set a to write _selectedText to _tempFile as «class utf8» starting at 1
close access _tempFile
display dialog "Pipe command?" default answer pPipeCommand buttons {"Cancel", "Run"} default button 2
set pPipeCommand to text returned of result
set _command to "cat " & _tempFilePath & " | " & pPipeCommand
set _output to do shell script _command
tell application "BBEdit"
make new text window at front
set selection of text window 1 to _output
end tell
end run
This is yet another idea, the two scripts are for creating and executing shell scripts with TextEdit, using their own extension “shellscript”, so that it is easy to double click on the script files in the finder and either edit or run them, after you have had a look at them. (I like to see them before I run them, if the script is made for a special task, and isn’t a subroutine.) The output from a shell script will be redirected to a new open TextEdit document.
You’ll need maverick, and The library posted under the title ConsoleIO here in Code Exchange.
The script below executes a shell script that is open in TextEdit.
Edit
You need to have Developer tools installed to use this, since I use the command SetFile.
use AppleScript version "2.3"
use scripting additions
use Output : script "Output"
tell application id "ttxt"
set docPath to path of its front document
try
set probe to docPath
on error
display alert "Save AND make executable first..."
error number -128
end try
end tell
set shFile to POSIX path of docPath
try
set theResult to do shell script quoted form of shFile
on error e number n
display dialog e
end try
if theResult is not "" then Output's initWithText("Output From: " & shFile & linefeed, 600, 800, theResult)
Output's leaveAtFront(0.5)
The script below creates a shell script of the front document in TextEdit and will make it so that it will always open in TextEdit, provided you give the script a “.shellscript” extension.
tell application id "ttxt"
set docPath to path of its front document
try
set probe to docPath
on error
display alert "Save first..."
error number -128
end try
end tell
set shFile to POSIX path of docPath
set sfxOfs to offset of ".txt" in shFile
try
if sfxOfs is not 0 then
set newSFile to text 1 thru (sfxOfs - 1) of shFile
do shell script "mv " & quoted form of shFile & space & quoted form of newSFile & "; chmod u+x " & quoted form of newSFile & "; SetFile -c \"ttxt\" -t \"ttxt\" " & quoted form of newSFile
set docPath to POSIX file newSFile as alias as text
else
do shell script "chmod u+x " & quoted form of shFile & "; SetFile -c \"ttxt\" -t \"ttxt\" " & quoted form of shFile
end if
on error e number n
display dialog e
end try
tell application id "sevs" to tell disk item docPath
set default application of it to "com.apple.textedit"
end tell