I need to see if a certain folder exists on a number of machines. Below is a simple example of what I have so far.
set thefolder to ((path to home folder) as text) & "My - Stuff"
set status to false as boolean
tell application "Finder" to if exists thefolder then set status to true
if status is true then
display dialog "Yes"
else
display dialog "No"
end if
The above code does work if the My - Stuff folder resides in the root of the home folder. If I move the folder under the Documents folder and change the first line to the following, the script does not work.
set thefolder to ((path to home folder) as text) & “Documents/My - Stuff”
The folder that I’m looking to find would be located as a subfolder under the Documents folder. I can’t seem to figure out what I’m doing wrong. Any help would be appreciated. Thanks.
Hi. Finder uses colons—not slashes—as path separators; that’s where the real problem lies. You could also avoid using the Finder, as extant items must resolve to an alias. Nitpicks: Any unquoted ‘false’ is automatically a boolean, so doesn’t need to be coerced to one. Things at the document folder level have a more direct reference than the home folder.
try
alias (((path to documents folder) as text) & "My - Stuff")
display dialog "Yes"
on error
display dialog "No"
end try
Marc’s explained about using colons instead of slashes in the path and has provided a simple overall solution.
To expand on his nitpicks (but only if you’re interested):
‘if’ reacts to booleans directly. In script code, it’s usually followed by some test which returns a boolean result — such as the Finder’s ‘exists’ command in your script. But it can also be followed by a variable containing a boolean or even (very rarely!) a hard-coded boolean. So code like …
set status to false as boolean
tell application "Finder" to if exists thefolder then set status to true
if status is true then
display dialog "Yes"
else
display dialog "No"
end if
… can be more efficiently rendered as:
tell application "Finder" to set status to (exists thefolder) -- Get the boolean result returned by the Finder.
if status then -- Use it.
display dialog "Yes"
else
display dialog "No"
end if
I see Stefan’s already added what I was going to say about ‘path to’.
on checkFolderExists(FolderToCheckString)
try
set thePath to quoted form of (POSIX path of FolderToCheckString)
do shell script "test -d " & thePath
return true
on error
return false
end try
end checkFolderExists
on checkFolderExists(FolderToCheckString)
return (do shell script "[[ -d " & quoted form of (POSIX path of FolderToCheckString) & " ]] && echo yes || echo no") as boolean
end checkFolderExists
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
on checkFolderExists(FolderToCheckString)
set {existsFlag, dirFlag} to current application's NSFileManager's defaultManager()'s fileExistsAtPath:(POSIX path of FolderToCheckString) isDirectory:(reference)
return existsFlag & dirFlag
end checkFolderExists
Although it’s massively faster than the shell versions, it has the same potential shortcoming: it regards packages as directories.
Easily fixed of course if that’s likely to be an issue:
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use framework "AppKit"
use scripting additions
on checkFolderExists(FolderToCheckString)
set thePath to current application's NSString's stringWithString:(POSIX path of FolderToCheckString)
set {existsFlag, dirFlag} to current application's NSFileManager's defaultManager()'s fileExistsAtPath:(thePath) isDirectory:(reference)
if (dirFlag) then set dirFlag to not (current application's NSWorkspace's sharedWorkspace's isFilePackageAtPath:(thePath))
return existsFlag & dirFlag
end checkFolderExists
Massive overhead of any do shell script is a pain indeed considering that the shell command itself (both examples) only takes 0.000001s. Getting rid of the echo commands makes mine twice as fast but I wanted to get rid of the design flaw (catch exception) as well. Again, the overhead of forking the current process into a new process, execve(), overshadows the differences.