Apple script to remove ._ files from USB drive - applescript

I need some help with an apple script that I can save on the computer so others can remove the ._ files from USB drives that are used for slide shows on TVs. I come from Linux so I pseudoed what I could.
usb_drives=$(ls /volumes/ | grep external) # intent
MyFlashDrive=$(prompt "Please select drive" usb_drives) # intent
dot_clean -m /Volumes/${MyFlashDrive} # mostly accurate

The AppleScript version of this would be something like the following:
tell application "System Events"
set ejactableDisks to get (displayed name of every disk whose ejectable is true)
--name of every file of home folder whose name begins with "."
end tell
set targetDiskName to choose from list ejactableDisks
tell application "System Events"
set targetDisk to first disk whose name is targetDiskName
set dotUnderscoreFiles to every file of targetDisk whose name begins with "._"
if (count of dotUnderscoreFiles) is greater than 0 then
delete dotUnderscoreFiles
end if
end tell
Of course, if you're more comfortable with unix you could write a bash routine and run it through do shell script, or just make an executable bash script.

Related

Script to find active wallpaper file in Finder under macOS Catalina

I used to use two AppleScript scripts to find out the file name of the actual wallpaper image from desktop 1 and desktop 2 (dual monitor mode) under macOS Mojave. One script for the main monitor and another one for the second monitor. Under macOS Catalina the scripts are not working anymore.
Here is the script:
tell application "System Events"
set posix_path to (pictures folder of desktop 2)
set picPath to (POSIX file posix_path) as string
end tell
set thePictures to (do shell script "sqlite3 ~/Library/Application\\ Support/Dock/desktoppicture.db \"SELECT data.value FROM preferences INNER JOIN data on preferences.key=16 and preferences.picture_id=7 and preferences.data_id=data.ROWID\"")
set fullPath to picPath as string
set rotationImage to fullPath & thePictures
tell application "Finder"
try
set aliasItem to item rotationImage
if class of aliasItem is alias file then
reveal original item of aliasItem
end if
end try
end tell
Here is the error message:
tell application "System Events"
get pictures folder of desktop 1
--> "/Users/peter/Library/Caches/com.apple.preference.desktopscreeneffect.desktop/69948584/DSKPhotosRootSource"
get POSIX file "/Users/peter/Library/Caches/com.apple.preference.desktopscreeneffect.desktop/69948584/DSKPhotosRootSource"
--> error number -1728 from POSIX file "/Users/peter/Library/Caches/com.apple.preference.desktopscreeneffect.desktop/69948584/DSKPhotosRootSource"
end tell
tell current application
do shell script "sqlite3 ~/Library/Application\\ Support/Dock/desktoppicture.db \"SELECT data.value FROM preferences INNER JOIN data on preferences.key=16 and preferences.picture_id=1 and preferences.data_id=data.ROWID\""
--> "13725B"
end tell
tell application "Finder"
get item "Macintosh HD:Users:peter:Library:Caches:com.apple.preference.desktopscreeneffect.desktop:69948584:DSKPhotosRootSource13725B"
--> error number -1728 from item "Macintosh HD:Users:peter:Library:Caches:com.apple.preference.desktopscreeneffect.desktop:69948584:DSKPhotosRootSource13725B"
end tell
Tried to find the problem but couldn't find a solution. I am not an experienced AppleScript writer. Hope somebody can help.
On Catalina and Mojave, I'm able to get the current wallpaper by using a sqlite command similar to yours:
sqlite3 ~/Library/Application\ Support/Dock/desktoppicture.db "select * from data" | tail -2
Or in Applescript:
do shell script "sqlite3 ~/Library/Application\\ Support/Dock/desktoppicture.db 'select * from data' | tail -2"
On my Mac, the last 2 items in the data table appear to be some combination of the most recently set wallpaper and last 2 displays that were most recently set, so I tail the list. Like you, I'm also using a large folder of wallpapers and I have it set to change every 30 minutes. As long as I don't manually change a wallpaper, the last 2 items are consistently the names of the 2 active wallpapers because both monitors change at the same time every 30 minutes.
Something to note: When you are using a Folder with the "Change picture:" checkbox checked, the items returned from select * data is just the file name (i.e., wallpaper.jpg). If you've set the wallpaper to a single image, the item returned from the select command is the full path of the image (i.e., /path/to/folder/wallpaper.jpg). Since I'm using a folder, so I get just the image names in my select results. Then I can split the 2 names by newline to get each wallpaper name in an array and then open them. Here's my whole script:
#!/bin/bash
#reads and opens the last 2 items from the 'data' table in the desktoppicture.db sqlite db
last_two=`sqlite3 ~/Library/Application\ Support/Dock/desktoppicture.db "select * from data" | tail -2`
IFS=$'\n' read -rd '' -a y <<<"$last_two"
#echo "first is ${y[0]}"
#echo "second is ${y[1]}"
open /Users/myusername/Pictures/Desktop\ Pictures/${y[0]}
open /Users/myusername/Pictures/Desktop\ Pictures/${y[1]}
I realize you asked an AppleScript question and this is largely a bash script answer, but the do shell script item at the top of my answer should get you going enough to be able to capture and manipulate the image names inside of AppleScript.
Just to close this out, I use this bash script in Alfred using a keyword "retire" to retire a wallpaper I'm tired of. I type the keyword, this script runs to open the images in Preview, another script runs to open my Desktop Pictures folder and a Desktop Pictures Retired folder and then I manually move the photo into the Retired folder.
If you currently have two monitors connected and you're simply looking to retrieve the names of the Desktop Wall Papers for each, this following Apple script code should be what you're looking for.
tell application "System Events"
set everyDesktop to desktops
set desktopOnePicture to picture of item 1 of everyDesktop
set desktopTwoPicture to picture of item 2 of everyDesktop
end tell
I can't guarantee the code below will fair any better than the solution already posted, but it should, in theory, target desktop images per screen (monitor) rather than by desktop (space). However, I don't have Mojave or Catalina, or a computer to test this out:
use framework "AppKit"
property NSScreen : a reference to NSScreen in the current application
property NSWorkspace : a reference to NSWorkspace in the current application
property currentScreen : a reference to the mainScreen of NSScreen
on screen(i as integer)
local i
if i = 0 then return the currentScreen()
return NSScreen's screens()'s item i
end screen
on desktopImageURLForScreen:(i as integer)
local i
set S to screen(i)
tell NSWorkspace's sharedWorkspace() to return the ¬
desktopImageURLForScreen_(S) as «class furl»
end desktopImageURLForScreen:
return the POSIX path of my desktopImageURLForScreen:0
The bottom line is the one you will most likely want to experiment with, by changing the index number passed to the handler. If you have three monitors, then they would each be identified by one of the indices 1, 2, or 3 (I can't predict how index corresponds to arrangement of monitors). Index 0 will always refer to the screen that currently has keyboard focus.

ApplescriptObjC path to disk (host drive)

As part of a larger project I would like to get the path of the Mount Point of the device which hosts my script.
I have designed the following code in Script Editor, however, upon implementing it in ApplescriptObjC (Xcode), I noticed that error started occuring.
# Get Mount Point of script USB host
tell application "Finder"
try
set usbMountPoint to text 1 thru -2 of POSIX path of (disk of (path to me) as alias)
log usbMountPoint # Output: /Volumes/usb-drive-name
on error
set usbMountPoint to POSIX path of (disk of (path to me) as alias) # if file is on desktop, path: '/', can't have '[space]' hence no removing
log usbMountPoint # Output: /Volumes/usb-drive-name
end try
end tell
Can’t make «class ocid» id «data optr00000000207F220080600000» into type constant. (error -1700)
I have included comments in the code as to how the logged output should look.
I understand that similar questions regarding the path to me problem in Xcode have been asked before, and that set myPath to current application's NSBundle's mainBundle()'s bundlePath() gives the current path, however, my question is concerning the disk of part of it.
Any help in getting the desired output in Xcode is greatly appreciated.
It requires a lot of coercions but the AppleScriptObjC equivalent in Xcode is
set myPath to current application's NSBundle's mainBundle()'s bundlePath() as text
tell application "Finder" to set mountPoint to POSIX path of (disk of item (myPath as POSIX file as text) as alias)
log mountPoint
The startup volume is represented by / all other volumes by /Volumes/<volumeName>

Moving .plist from usb drive to local disk using applescript

I've been trying to figure this one out for a while now, and I've hit a bit of a wall.
I have quite a few Macs in my environment, and for inventory purposes I need to copy a file named "Department-Info.plist" from a USB Drive to the following location on the hard drive
Macintosh HD:Library:Application Support:Dell:KACE:
I've come up with a couple of solutions that I thought might work, and believe I'm on the right track. However, I'm not getting the result I'm looking for.
Below is what I've come up with thus far, but I need to complete this task:
tell application "Finder"
activate
set FileToMove to "VOLUMES:DELL KACE:Mac:Department-Info.plist"
set FinalLoc to "Macintosh HD:Library:Application Support:Dell:KACE:"
copy file FileToMove to FinalLoc
end tell
I receive this error message when running this script:
I've also tried using this variation of the script:
tell application "Finder"
activate
set name of document file "Department-Info.plist" of folder "Mac" of disk "DELL KACE" to "Department-Info.plist"
set FinalLoc to "Macintosh HD:Library:Application Support:Dell:KACE:"
copy "Department-Info.plist" to FinalLoc
end tell
However, this yields the following result.
I wondered if anyone could point me in the right direction, or provide resources that I may have missed.
First of all, the command copy assigns a value to a variable, it does not copy files
The correct code is
tell application "Finder"
-- activate is not needed
set FileToMove to "DELL KACE:Mac:Department-Info.plist"
set FinalLoc to "Macintosh HD:Library:Application Support:Dell:KACE:"
duplicate file FileToMove to folder FinalLoc
end tell
However consider that you might not have sufficient access privileges to copy the file.
In this case you need to use the shell to enter an admin password:
do shell script "cp '/Volumes/DELL KACE/Mac/Department-Info.plist' '/Library/Application Support/Dell/KACE/'" with administrator privileges

Applescript to copy files based on partial file name

Forgive me, I'm a bit of an amature.
I'm working to comply with a records request for hundreds of students. All files are named with the first 5 digits of the name being the student's ID number. I created the script below and it runs but with no results.
I would welcome any help that you guys can provide.
with timeout of 3600 seconds
tell application "Finder"
set myFiles to files of folder POSIX file "/Volumes/Storage/Records" as alias list
end tell
repeat with aFile in myFiles
tell application "System Events"
set myvalues to {"11111", "22222", "33333", "44444", "55555", "66666", "77777", "88888", "99999", "00000", "11112", "22223", "33334", "44445", "55556", "66667", "77778", "88889", "99990"}
if name of aFile contains myvalues then
copy aFile to folder POSIX file "/Volumes/Storage/Records"
end if
end tell
end repeat
end timeout
First of all, the command to copy files in terminology of Finder and System Events is duplicate.
Second of all (and the main issue) you have to check the first 5 characters not the entire name.
And third of all, it’s not quite useful to copy the files to the same place but I guess it’s only a placeholder
property IDNumbers : {"11111", "22222", "33333", "44444", "55555", "66666", "77777", "88888", "99999", "00000", "11112", "22223", "33334", "44445", "55556", "66667", "77778", "88889", "99990"}
with timeout of 3600 seconds
tell application "Finder"
set myFiles to files of folder "Storage:Records:"
repeat with aFile in myFiles
set IDPrefix to text 1 thru 5 of (get name of aFile)
if IDPrefix is in IDNumbers then
duplicate aFile to folder "Storage:Records:Destination:"
end if
end repeat
end tell
end timeout
My solution uses only the Finder because it doesn't include the invisible files and it's not needed to coerce the Finder object specifiers to alias.
If the location of the files is on an external volume, it’s easier to use the HFS path “Storage:Records” than the coercion from POSIX path POSIX file "/Volumes/Storage/Records” as alias
I suggest you to use do shell script function instead of using Finder application as it's more flexible solution. And you can find any errors in your command easily because you can debug it using the Terminal.
do shell script "<your commands here>"
For your use case you need to use a couple of commands inside do shell script: find and then cp.
I would suggest a simple bash script is a better option here. Save the following script on your Desktop as CopyFiles
#!/bin/bash
# Make a subdirectory to copy the results to
mkdir results 2>/dev/null
# Read all ids from file "ids.txt"
while read id; do
echo Processing id: $id
# Remove the word "echo" on following line to actually copy files
echo cp /Volumes/Storage/Records/${id}* results
done < ids.txt
It assumes there is a file on your Desktop called ids.txt that looks like this
11111
22222
12345
54321
Then start a Terminal, by pressing Cmd+Spacebar and typing "Terminal" and hitting "Enter".
Go to your Desktop and make the script executable with
cd Desktop
chmod +x CopyFiles
and then run it with
./CopyFiles
At the moment, it does nothing except tell you what it would do like this:
Processing id: 11111
cp /Volumes/Storage/Records/11111* results
Processing id: 22222
cp /Volumes/Storage/Records/22222* results
Processing id: 12345
cp /Volumes/Storage/Records/12345* results
Processing id: 54321
cp /Volumes/Storage/Records/54321* results
If it looks like it is doing what you want, edit the script and remove the word echo where noted and run it again.

Tell application process that contain a word

This question may seem strange. However I'm in the need of interacting with an application that is releasing worldwide with different names, eg. AppEN, AppGB, AppDE etc...
I am looking for a solution that allow me to use this command:
tell application process "AppnameGB"
However it should work with all the different variations of this application. I don't know if this is possible but searching for a string in the application name could do the trick: tell application process that contain in its name "Appname".
If the process is already open, you can use something like this:
tell application "System Events"
tell (process 1 where name starts with "TextEd")
properties
set f to its file
end tell
end tell
tell application (f as text)
properties
end tell
Telling Finder to list files is really slow:
tell application "Finder"
item 1 of (path to applications folder) where name starts with "Text"
end tell
You can use do shell script though:
set a to do shell script "ls /Applications/ | grep -m1 '^Text.*\\.app$'"
tell application a
properties
end tell
set a to do shell script "mdfind 'kMDItemContentType==com.apple.application-bundle&&kMDItemFSName==Text*' | head -n1" would also search outside the applications folder.
The easiest is if you could use the bundle identifier of the application instead of its name. Most likely the bundle ID doesn't change while the name does. So use this script on that application and check if the bundle ID changes or not.
tell application "Finder" to set bundleID to id of (choose file)
If you find it doesn't change then you can access it via applescript like this...
tell application "com.bundle.id"
activate
-- do something
end tell
Your only other alternative is get a list of all applications, and loop through them checking the name as you suggest. Something like this wold work but is pretty slow.
-- use spotlight to find all the apps on the computer
set cmd to "mdfind 'kMDItemContentType == \"com.apple.application-bundle\"'"
set foundApps to paragraphs of (do shell script cmd)
-- search the found apps looking for the one you're interested in
set appPath to missing value
repeat with i from 1 to count of foundApps
if (item i of foundApps) contains "Appname" then
set appPath to item i of foundApps
exit repeat
end if
end repeat
if appPath is missing value then error "Couldn't find the app!"
-- open the app
set macAppPath to (POSIX file appPath) as text
tell application macAppPath
activate
-- do something
end tell

Resources