In my attempt to AppleScript a path to a file on a shared Google Drive, I noticed that the path assigned to the file by Google Drive, can vary between users.
On my Mac , the path
/Volumes/GoogleDrive/
permits retrieval of files from the shared Google Drive. On other users’ Macs, where Google Drive is not mounted in the Volumes directory, access to the shared Google drive file requires a path through Cloud Storage, beginning with
It appears to me that Google Drive maintains various account mount points, one through the Volumes directory and the other via Library’s Cloud Storage. Although the Google Drive preferences on my Mac contain these two mount points, other users preferences’ mount points only contain a Cloud Storage path.
My goal is to write an AppleScript that can locate the path to a file on this shared Google Drive, regardless of the user’s email address, so that AppleScript will locate a file on any Mac that has access to this shared Google Drive.
I have written a script that finds the Google Drive Path from a retuned JSON(?) from the defaults read command of Google Drives Preferences. This will allow the script on multiple users’ Macs and capture their Google Drive account and email information. The script will then construct a pix path so that files on the shared Google Drive can be accessed.
set GoogleDriveLocalPart to "Local-Part" --insert GoogleMailuser name
set GoogleDriveDomainName to "DomainName.com" --insert domaine name referenced by Google Drive
set GoogleDriveFullEmail to GoogleDriveLocalPart & "@" & GoogleDriveDomainName
set GoogleDriveRootPath to my ConstructGoogleDriveRootPathUsingGoogleDriveEmail:GoogleDriveFullEmail
on ConstructGoogleDriveRootPathUsingGoogleDriveEmail:GoogleDriveFullEmail
# Read Google Drive Preferences
set jsonString to do shell script "defaults read ~/Library/Preferences/com.google.drivefs.settings"
# Parse Google Drive's mount point path that corresonds to the GoogleDrive domaine name
set text item delimiters to "mount_point_path"
# Convert list to text
set jsonStringTextItems to text items of jsonString
repeat with jasonStringItems in jsonStringTextItems
set jsonStringText to contents of jasonStringItems as string
# Identifty a string that reflects the user's library path
if "Users" is in jsonStringText then
# Get the start of the Google Drive path
set pathStart to "/Users"
set text item delimiters to pathStart
# Rebuild the GoogleDrive posix path
set PathRemainderBlock to text item 2 of jsonStringText
# Get the end of the Google Drive root path
set PathEnd to "/GoogleDrive-" & GoogleDriveFullEmail
set text item delimiters to PathEnd
# Get the remaining middle of the GoogleDrive posix path
set PathMiddle to text item 1 of PathRemainderBlock
# Reconstruct the Posix Path
set GoogleDrivePath to pathStart & PathMiddle & PathEnd
return GoogleDrivePath
end if
end repeat
GoogleDrivePath
end ConstructGoogleDriveRootPathUsingGoogleDriveEmail:
I tried to script Foundation’s NSJSONSerialization, unsuccessfully with the following code:
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
set jsonString to do shell script "defaults read ~/Library/Preferences/com.google.drivefs.settings"
set jsonList to (current application's NSJSONSerialization's JSONObjectWithData:((current application's NSString's stringWithString:jsonString)'s dataUsingEncoding:(current application's NSUTF8StringEncoding)) options:0 |error|:(missing value))
As my Foundation’s NSJSONSerialization produced no response, I would like to hear your ideas to decode this Google Drive JSON response
I do not know why I did not see this simple solution earlier. Google’s root directory structure can be accessed via Google Drive’s folder, located in the home folder.
set home to do shell script "echo $HOME"
set GoogleDrive to home & "/Google Drive/"
Now that I have gained access to Google Drive using the home path & “/Google Drive/”, my following attempt a find a folder, named “Shared”, in that directory failed.
set home to do shell script "echo $HOME"
set GDPath to home & "/Google Drive/"
set findSh to "find " & quoted form of (GDPath) & " -iname " & quoted form of "*Shared*" & " -type d"
do shell script findSh
When I ran the findSh string in Terminal, the command returned an error that the operation was not permitted
find: /Users/alan/Google Drive/: Operation not permitted
I am looking for ways to AppleScript a command to find a folder in Google Drive For Desktop, and I appreciate all ideas.
The simplest way to test the existence of a file or folder is:
set theFolder to ("" & (path to home folder) & "Google Drive:Shared:")
theFolder as alias
Triggers an error if no file/folder exists at this path.
Or an AppleScriptObjC variation:
use framework "Foundation"
use framework "AppKit"
use scripting additions
set thePath to current application's NSHomeDirectory()'s stringByAppendingString:"/Google Drive/Shared/"
set theURL to current application's NSURL's fileURLWithPath:thePath
theURL's checkResourceIsReachableAndReturnError:(missing value)
Thank you, Ionah. Your idea to use the checkResourceIsReachableAndReturnError instance method confirmed the existence of a file in the Google Drive, and addressed my initial post question.
Now that you answered that question and I can access Google Drive, I would like to find a Google Drive file, whose name I do not completely know but for whom I have several variables.
Prior to Google Drive’s removal of its /Volumes/ mount point, I used a do shell script using unix’s find command. Since the change in Google’s mount point, it appears that Google Drive does not permit such find operation.
Do you have any ideas how to perform a find operation in Google Drive’s new environment, via alternative means?
Attempting to use the find shell script in a Directory whose path is composed of my library’s CloudStorage path, using the concatenation of “GoogleDrive” and my GoogleAccountEMailAddress, in the configuration succeeded in finding a file without error.
set TargetDirectory to "/Users/alan/Library/CloudStorage/GoogleDrive-" & GoogleAccountEMailAddress & "/Shared drives/"
set findSh to "find " & quoted form of TargetDirectory & ¬
space & "-iname" & space & "*" & quoted form of LN & "*" & ¬
space & "-iname" & space & "*" & quoted form of FN & "*"
set FoundFiles to do shell script findSh
Attempting to perform the same shell script in the TargetDirectory now accessed via “/Users/alan/Library/Google Drive/Shared drives/” yielded “No such file or directory”
set TargetDirectory to "/Users/alan/Google Drive/Shared drives/"
set findSh to "find " & quoted form of TargetDirectory & ¬
space & "-iname" & space & "*" & quoted form of LN & "*" & ¬
space & "-iname" & space & "*" & quoted form of FN & "*"
set FoundFiles to do shell script findSh
--> "No such file or directory"
When I used “NSFileManager’s defaultManager()'s contentsOfDirectoryAtURL:” method together with “filteredArrayUsingPredicate:theNSCompoundPredicate” as in the following script, both paths, ie
The following script succeeded in finding a file with both directory path configurations.
on FindFN:FN LN:LN Directory:DirectoryPath
set RegularFileKey to current application's NSURLIsRegularFileKey
set aliasKey to current application's NSURLIsAliasFileKey
set noPackageContents to current application's NSDirectoryEnumerationSkipsPackageDescendants
set noHiddenFiles to current application's NSDirectoryEnumerationSkipsHiddenFiles
set fileManager to current application's NSFileManager's defaultManager()
set DirectoryContentsArray to (current application's NSFileManager's defaultManager()'s ¬
contentsOfDirectoryAtURL:(current application's |NSURL|'s fileURLWithPath:DirectoryPath) ¬
includingPropertiesForKeys:{} ¬
options:(noPackageContents + noHiddenFiles) |error|:(missing value))
if DirectoryContentsArray is missing value then return missing value -- otherwise continue script
set PredicateArray to {LN, FN}
set NSComparisonPredicateList to {}
repeat with PredicateItem in PredicateArray
set Predicate to contents of PredicateItem
set end of NSComparisonPredicateList to (current application's NSPredicate's ¬
predicateWithFormat:"%K CONTAINS[c] %@" argumentArray:{¬
"lastPathComponent.stringByDeletingPathExtension", Predicate})
end repeat
set NSComparisonPredicateArray to current application's NSArray's arrayWithArray:NSComparisonPredicateList
# Convert Comparison Predicate array to a Compound Predicate array
set theNSCompoundPredicate to current application's NSCompoundPredicate's andPredicateWithSubpredicates:NSComparisonPredicateArray
set theNSURLArray to DirectoryContentsArray's filteredArrayUsingPredicate:theNSCompoundPredicate
return (POSIX path of (theNSURLArray's firstObject() as string))
end FindFN:LN:Directory:
I am looking for some insight as to the reasons for the Google Drive path configuration not upsetting to NSFileManager’s defaultManager but throwing an error with the shell’s find command.
Does NSFileManager’s defaultManager view its directory structure differently than the shell?
Does NSFileManager perform a hidden synchronization function to convert between the two Google Drive path configurations, via some type of CloudStorage’s utility?
If so, is there a method to view this function and its results, to manipulate it or to affirm its results with AppleScript?
1 &2: The double slash seems suspect here. Is it a typo in your post or does your script uses this path?
3: Not sure what you mean but contentsOfDirectoryAtURL can’t return a path if the file does not exists.
Your handler could be simplified:
set theFM to current application's NSFileManager's defaultManager()
set theURL to (current application's |NSURL|'s fileURLWithPath:DirectoryPath)
set DirectoryContentsArray to (theFM's contentsOfDirectoryAtURL:theURL includingPropertiesForKeys:{} options:6 |error|:(missing value))
if DirectoryContentsArray is missing value then return missing value -- otherwise continue script
set thePattern to "lastPathComponent.stringByDeletingPathExtension"
set thePred to (current application's NSPredicate's predicateWithFormat:"%K CONTAINS[c] %@ OR %K CONTAINS[c] %@" argumentArray:{thePattern, FN, thePattern, LN})
set theNSURLArray to DirectoryContentsArray's filteredArrayUsingPredicate:thePred
return (theNSURLArray's valueForKey:"path") as list
return item 1 of (theNSURLArray's valueForKey:"path") as list -- if you only need the fist item
Ionah,
Thanks for finding the double forward slash typographical error, and I have since corrected that error in the original post.
Regarding your simplification of the handler, I appreciate your comments to make it easier.
Regarding the contentsOfDirectoryAtURL method, what perplexes me is that the function returns positive responses in both following path syntaxes.
Given this positive response to finding the same URL, ostensibly generated by NSFileManager’s default manager, I wanted to know more about the details of this process, so that I could evaluate NSFileManagers’ underlying approach to this method. Could the generation of the same URL
Arise solely as a Google Drive action in the user’s CloudStarge directory inside the user’s library?
Arise solely from the NSFileManager object?
Arise from some other object or method, of which I am unaware?