Handler for escaping a filepath for POSIX conformance

The structure of this code was influenced by some code Apple posted under “Changing Case” here. Escaping is much better than quoting, especially if you want to build on a POSIX path by adding things to it. I have a similar handler in the latest script I’ve uploaded.

on escapepath(filepath)
	set evildoers to "*?[]^{}~$!^&|<>;()`\\'\" 	"
	set escaped to {}
	set filepath to filepath as text
	set filepath to POSIX path of filepath
	set AppleScript's text item delimiters to "/"
	set filepath to text items of filepath as list
	set AppleScript's text item delimiters to ""
	repeat with seg in filepath
		repeat with char in seg
			set evil to offset of char in evildoers
			if evil ≠ 0 then
				set escaped to escaped & "\\" & char
			else
				set escaped to escaped & char
			end if
		end repeat
		set escaped to escaped & "/"
	end repeat
	set escaped to escaped as text
	set escaped to items 1 through -2 of escaped as text
	return escaped
end escapepath

Can’t you do something like this?:

set flurryPath to "/System/Library" & quoted form of "/Screen Savers" & "/Flurry.saver"
--> "/System/Library'/Screen Savers'/Flurry.saver"
do shell script "cd " & flurryPath & "; pwd"

I thought that at first Qwerty, but I can imagine someone wanting to do this. However, it’s really just a specialized find/replace script (as compared to these threads: str_replace(), Find & Replace).

Side note: We have a topic on changing text case: Change Text Case

Edit: I don’t understand why you’re breaking up the path when you escape the characters. Looping over each character in the path will probably have a performance impact (if you measure such things). I’m not used to using offset, so here’s a delimiter-based version:

-- somePath must be some sort of text
on escapePOSIX(somePath)
	set ASTID to AppleScript's text item delimiters
	set escapeNeeded to {"\\", space, ASCII character 34, tab, "(", ")", "[", "]", "{", "}", "<", ">", "|", "!", "?", "$", "~", "^", "*", "`", "'", ";", ASCII character 27}
	
	try
		repeat with thisChar in escapeNeeded
			set AppleScript's text item delimiters to {thisChar}
			set somePath to text items of somePath
			
			set AppleScript's text item delimiters to {"\\" & thisChar}
			set somePath to "" & somePath
		end repeat
	end try
	
	set AppleScript's text item delimiters to ASTID
	return somePath
end escapePOSIX

escapePOSIX("/System/Library/Screen Savers/Flurry.saver")
--> "/System/Library/Screen\\ Savers/Flurry.saver"

Oh, snap!

Thanks, Bruce Phillips :smiley:

hmm -

in this part of your script:

   set escapeNeeded to {"\\", space, quote, tab, "(", ")", "[", "]", "{", "}", "<", ">", "|", "!", "?", "$", "~", "^", "*", "`", "'", ";", ASCII character 27}

“quote” wasn’t recognized by my version of applescript. So, instead, I used ASCII character 34 for quote.

Thanks for pointing that out; I’ve changed my script above. (quote became a constant in AppleScript v1.10.)

Very nice idea, Alex, and nice implementation too, Bruce. Something very similar could help with shell scripts like the one below and its escaped version below:

echo $PATH | sed -e 's/:/ /g' | xargs -J % find % -maxdepth 1 \( -type f -or -type l \) | xargs basename | sort | uniq | xargs whatis 2> /dev/null | grep -E '\((1|1m|6|8)\)' | perl -ne '($name, $descrip) = m/^(.*?)\s+- (.*)$/; $name =~ s/\((1|1m|6|8)\)//g; printf("%-20s - %s\n", $name, $descrip)' > ~/desktop/Unix_Functions.txt
do shell script "echo $PATH | sed -e 's/:/ /g' | xargs -J % find % -maxdepth 1 \\( -type f -or -type l \\) | xargs basename | sort | uniq | xargs whatis 2> /dev/null | grep -E '\\((1|1m|6|8)\\)' | perl -ne '($name, $descrip) = m/^(.*?)\\s+- (.*)$/; $name =~ s/\\((1|1m|6|8)\\)//g; printf(\"%-20s - %s\\n\", $name, $descrip)' > ~/desktop/Unix_Functions.txt"

Offhand, I think this should work:

-- A valid shell script should be on the clipboard
set shellScript to the clipboard
set ASTID to AppleScript's text item delimiters
set escapeNeeded to {"\\", "\""}

try
	repeat with thisChar in escapeNeeded
		set AppleScript's text item delimiters to {thisChar}
		set shellScript to text items of shellScript
		
		set AppleScript's text item delimiters to {"\\" & thisChar}
		set shellScript to "" & shellScript
	end repeat
end try

set AppleScript's text item delimiters to ASTID
set the clipboard to "do shell script \"" & shellScript & "\""
beep

I am using the escapePOSIX() handler in an AS Studio application that launches a command line app that is kept within the Contents/Resources/ folder of the application. I just wanted to say that this handler works terrifically!

I did come across one problem and I was wondering if anyone knows of a solution.

A Japanese user is getting less than optimal results with my app as it is unable to find the command line utility. I believe this is due to a mistranslation of the POSIX path when Japanese characters are present.

Here is the context of my use of the escapePOSIX() handler:


    set POSPath to POSIX path of (path to me)
    set rPath to POSIX path of POSPath & "Contents/Resources/kaid/"
    set kaidPath to escapePOSIX(rPath)
    set setLogFile to ((path to temporary items) as Unicode text) & "kaidEngineLog.txt"
    set theLogFile to POSIX path of setLogFile
    set kaidPass to content of text field "startKaidWith" of window "prefs"
    
    do shell script "cd " & kaidPath & "; ./kaid -c kaid.conf &> " & theLogFile & " &" password kaidPass with administrator privileges
    do shell script "sudo -k"

The error he is getting is:

/bin/sh: line 1: ./kaid: No such file or directory

I got this same error, I believe due to a space in the name of the app (Kaid Commander) which was remedied by this wonderful escapePOSIX() handler, and I believe that there may be something related to the Japanese characters that is causing some sort of escape problem.

Does anyone have any ideas on a possible solution?

Perhaps I am going about this all wrong to begin with and there is a better way to launch this item?

-sD-
Dr. Scotty Delicious, Scientist.

Try using quoted form instead:

set kaidPass to content of text field "startKaidWith" of window "prefs"
set kiadExec to quoted form of POSIX path of ((path to me as Unicode text) & "Contents:Resources:kaid:kaid")
set logPath to quoted form of POSIX path of ((path to temporary items as Unicode text) & "kaidEngineLog.txt")

do shell script kaidExec & " -c kaid.conf &> " & logPath & " &" password kaidPass with administrator privileges

Aha.
Wonderful. I will apply this and report back on the results.

Thank you,

-sD-
Dr. Scotty Delicious, Scientist.

Hi Adam, while looking at this thread, I thought that a script idea from there could also help with the above script. and save escaping for applescript.

example

on ACom_run(script_text, Code)
    
    set the_name to name of document 1
    set the_contents to contents of document the_name
    set AppleScript's text item delimiters to ("Start_Point_" & Code as string)
    set the_content to text item -1 of the_contents -- this works from bottom of text to first break point  "Script_Start_Point"
    set AppleScript's text item delimiters to ("End_Point_" & Code as string)
    set script_text to text item 1 of the_content
    set AppleScript's text item delimiters to ""
    return script_text
end ACom_run


set script_text to ""
set Code to "Shell1"
set shell_text to ACom_run(script_text, Code)
do shell script shell_text
-- Adams shell script 
--  Start_Point_Shell1 echo $PATH | sed -e 's/:/ /g' | xargs -J % find % -maxdepth 1 \( -type f -or -type l \) | xargs basename | sort | uniq | xargs whatis 2> /dev/null | grep -E '\((1|1m|6|8)\)' | perl -ne '($name, $descrip) = m/^(.*?)\s+- (.*)$/; $name =~ s/\((1|1m|6|8)\)//g; printf("%-20s - %s\n", $name, $descrip)' > ~/desktop/Unix_Functions.txt End_point_Shell1  


set Code to "Shell2"
set shell_text to ACom_run(script_text, Code)
set ass to do shell script shell_text
-- A Cameron Hayne shell script to find urls in a file 
-- Start_Point_Shell2 perl -ne 'if (/src="([^"]*)"/) { print "$1\n"; }'  path/to/Foo  > ~/desktop/Unix_Functions2.txt End_point_Shell2

I was just having a last look when I saw this Mark, but I confess I don’t know what document 1 is supposed to be.

Its the open document. (The script itself)
Which does limit the using of commenting this way to scripts run from Script editor some what. :rolleyes:
(Unless I can find a way to read the script file and coerce it into text.)

Using “quoted form of” worked brilliantly.

Thank you.

-sD-
Dr. Scotty Delicious, Scientist.