AppleScript file path difficulties

I’m trying to create a script that will do two things: 1) check for the existence of certain files, and 2) move those files to the trash. I need to do #1 so that I can tell the user that a particular set of files was found and removed, and I need to do #2 using a shell script with admin privileges.

The code I’ve written so far works great, as long as I use absolute paths. As soon as I try to refer to the user folder using the tilde (‘~’) symbol, though, it all falls apart. Although I can hard-code the paths for the most part, I cannot hard-code the username.

How can I make this work for a path in the user’s home folder? The code in question is below:


– Given a list of path strings, returns a list of POSIX paths, quoted for use in shell scripts

on CreateQuotedPOSIXPathList(pathStrings)

set thePOSIXPaths to {}

repeat with thePath in pathStrings
	set thePOSIXPaths to thePOSIXPaths & {quoted form of the POSIX path of thePath}
end repeat

return thePOSIXPaths

end CreateQuotedPOSIXPathList


– Given a list of quoted-form POSIX file paths, moves all files in the set to the trash
– Returns true if at least one file was found, false if none existed

on MoveFilesToTrash(fileList)

set someWereFound to false

repeat with oneFile in fileList
	if exists oneFile then
		set someWereFound to true
		set theCommand to "mv " & oneFile & " ~/.Trash"
		do shell script theCommand with administrator privileges
	end if
end repeat

return someWereFound

end MoveFilesToTrash

set fileList to {“/Users/thomas/Desktop/test folder”, “/Users/thomas/Desktop/test file”}
set pathList to CreateQuotedPOSIXPathList(fileList)
MoveFilesToTrash(pathList)

Hi,

there are some issues in your script.

¢ The line


 if exists oneFile then

returns always true because the literal path representation exists always.
To check the existence of a file or folder object you need to ask the Finder or System Events.

¢ In the CreateQuotedPOSIXPathList() handler you are creating POSIX paths from POSIX paths, which could cause unexpected behavior. When you’re passing a list of POSIX paths anyway, do not coerce them.
I recommend also to add the quotation in the other handler.

To use a relative path
path to home folder returns always the alias specifier to the home folder of the current user.


set fileList to {"/Users/thomas/Desktop/test folder", "/Users/thomas/Desktop/test file"}
set success to MoveFilesToTrash(fileList)

on MoveFilesToTrash(fileList)
	
	set someWereFound to false
	set trashFolder to POSIX path of (path to home folder) & ".Trash"
	repeat with oneFile in fileList
		tell application "System Events" to set fileExists to exists file oneFile
		if fileExists then
			set someWereFound to true
			set theCommand to "mv " & quoted form of oneFile & space & trashFolder
			do shell script theCommand with administrator privileges
		end if
	end repeat
	
	return someWereFound
end MoveFilesToTrash


Thanks for the suggestions!

Unfortunately, it’s still not working. It doesn’t seem to recognize the existence if an item is a folder, and the shell command still doesn’t seem to like the path if it contains a tilde.

Here’s the code I’ve got now:

-----------------------------------------------------------------------
-- Given a list of quoted-form POSIX file paths, moves all files in the set to the trash
-- Returns true if at least one file was found, false if none existed
-----------------------------------------------------------------------
on MoveFilesToTrash(fileList)
	
	set someWereFound to false
	
	set trashFolder to POSIX path of (path to home folder) & ".Trash"
	repeat with oneFile in fileList
		tell application "System Events" to set fileExists to exists file oneFile
		if fileExists then
			set someWereFound to true
			set theCommand to "mv " & quoted form of oneFile & space & trashFolder
			do shell script theCommand with administrator privileges
		end if
	end repeat
	
	return someWereFound
	
end MoveFilesToTrash

set fileList to {"~/Desktop/test folder", "~/Desktop/test file"}
MoveFilesToTrash(fileList)

The results are:

tell application “System Events”
exists file “~/Desktop/test folder”
→ false
exists file “~/Desktop/test file”
→ true
end tell
tell current application
do shell script “mv ‘~/Desktop/test file’ /Users/thomas/.Trash” with administrator privileges
→ error “mv: rename ~/Desktop/test file to /Users/thomas/.Trash/test file: No such file or directory” number 1
Result:
error “mv: rename ~/Desktop/test file to /Users/thomas/.Trash/test file: No such file or directory” number 1

(BTW, the “~/.Trash” part in the original code was not the part that was failing… it was if I changed the “/Users/thomas” part.)

Since I’m hard coding the paths, I could always just use something like:

path to home folder & “Desktop/test file”

However, I’d like to understand more about this, and how to interchange a fully shell-compatible path for an AppleScript-compatible one, and vice versa. And, of course, there’s still the issue of not seeing that the folder exists.

Sorry, at first glance fileList implies that only files are passed.
You can use a relative path also for the desktop folder of the current user


on MoveItemsToTrash(itemList)
	
	set someWereFound to false
	
	set trashFolder to POSIX path of (path to home folder) & ".Trash"
	repeat with oneItem in itemList
		tell application "System Events" to set itemExists to exists disk item oneItem
		if itemExists then
			set someWereFound to true
			set theCommand to "mv " & quoted form of oneItem & space & trashFolder
			do shell script theCommand with administrator privileges
		end if
	end repeat
	
	return someWereFound
	
end MoveItemsToTrash

set desktopFolder to POSIX path of (path to desktop folder)
set fileList to {desktopFolder & "test folder", desktopFolder & "test file"}
MoveItemsToTrash(fileList)


The problem strike when you ask the script to execute :

quoted form of the POSIX path of thePath

If my memory is right, the tilde shortcut is not officially supported by Os X.
When thePath is an official path like :

/Users/thomas/Desktop/test folder

the result is ‘/Users/thomas/Desktop/test folder’

But, when thePath is ~/Desktop/test folder,
the system doesn’t recognize a valid path name but a string supposed to be a file name.
So, it convert the embedded slash ” not allowed in a Posix filename ” into colons,
so the result is ‘/~:Desktop:test folder’

As you are using Posix pathnames in the caller code, why are you asking the handler to convert them into Posix Path which is the wrongdoer.

Use the code :
set thePOSIXPaths to thePOSIXPaths & {quoted form of thePath}

and you will get a correct behavior.

If, for some reason you really need to use the original instruction
set thePOSIXPaths to thePOSIXPaths & {quoted form of the POSIX path of thePath}
use HFS pathnames as starting ones :

set p2d to path to desktop as text
set fileList to {p2d & “test folder”, p2d & “test file”}

Don’t try to use POSIX file to convert your unsupported pathnames, because
POSIX file “~/Desktop/test folder”
returns
file “:~:Desktop:test folder”

You may think that it’s an odd behavior but, it’s your job to take care of what is supported and what isn’t.

An awful workaround may be :
if thePath starts with “~” then
set thePOSIXPaths to thePOSIXPaths & {quoted form of thePath}
else
set thePOSIXPaths to thePOSIXPaths & {quoted form of the POSIX path of thePath}
end

As ~ has some meaning in POSIX path but none in HFS ones,
the short instruction will be used only if you ask it to treat an unsupported POSIX path,
the long one will treat the supported POSIX paths as well as HFS ones.

Yvan KOENIG (VALLAURIS, France) mardi 29 avril 2014 17:23:18

Hi,

fyi since you’re using unix, you could also use the ‘find’ command. It also allows you to -delete the item (I think) without leaving it in the trash. Just another option. Although, learning about Mac paths is good also.

gl,
kel

Ahh, bingo! That’s got it working! Thanks!

Mostly because I have always had difficulty with AppleScript and paths, and thought I was doing it right! :slight_smile:

I think it’s a bit clearer now, although this kind of thing is the reason why I haven’t liked AppleScript much. For a language with such “plain English” wording, it can be awfully abstruse sometimes and very picky about syntax. And the methods for interacting with files have always seemed like an odd mix of old pre-Mac OS X HFS and Unix, with alias data thrown in for good measure, that is difficult to wrap my head around.

In any case, though, I’ve got it working now. Thanks for the help!

Hello

I retrieved the thread in which the fact that ~paths aren’t supported.
Dated 2003/10/22, it contains the sentence :
(There is an enhancement request filed on this.)

but nothing arrived.

It contains also the tip solving your problem.

In your original script, edit :

set thePOSIXPaths to thePOSIXPaths & {quoted form of the POSIX path of thePath}
as
set thePOSIXPaths to thePOSIXPaths & {quoted form of POSIX path of (do shell script "echo " & thePath)}

And your code will be OK for
HFS paths
supported UNIX paths
unsupported UNIX paths (those starting with ~)

As you aren’t forced to trust me, you may look at :

http://lists.apple.com/archives/applescript-users/2003/Oct/msg00656.html

Yvan KOENIG (VALLAURIS, France) jeudi 1 mai 2014 17:44:01