Copy files to several USB Sticks with AppleScript - applescript

I have to copy files to a lot of USB-Sticks. Therefore I´m trying to write me a short applescript. I´m not familiar with applescript so it would be great if someone can give me some hints.
What I have so far:
10 places USB-Hub
A short script to rename the sticks.
Now I´m stuck in copying the files to every stick which is connected:
property ignoredVolumes : {"Macintosh HD", "Time Machine Backups"}
set myPath to ("Macintosh HD:Users:myusername:USB-Stick") as string
tell application "System Events"
set rootVolume to disk item (POSIX file "/Volumes" as text)
set allVolumes to name of every disk item of rootVolume
repeat with aVolume in allVolumes
if aVolume is not in ignoredVolumes then
set name of disk item (path of rootVolume & aVolume) to "Stickname"
end if
end repeat
end tell
What I now need to do is to copy from myPath to every USB-Stick which is connected. Because they all get the same name, they will mounted with numbers behind the name (Stickname, Stickname 1,Stickname 2, ...)
So I need to add in my loop the copy command to the just renamed stick.
Hope someone could give me a helping hand.

It would be easier to do with a shell script:
do shell script "cp -R ~/USB-Stick/ /Volumes/Stickname*"

You can try something like this:
property ignoredVolumes : {"Macintosh HD", "Time Machine Backups", "iDisk", "net", "home"}
set myPath to (path to home folder as text) & "USB-Stick:"
tell application "System Events" to set theDisks to every disk
repeat with aDisk in theDisks
if aDisk's name is not in ignoredVolumes then
set diskPath to path of aDisk
tell application "Finder" to duplicate myPath to diskPath with replacing
end if
end repeat

thanks for your hints. I solved it now with the following code:
property ignoredVolumes : {"Macintosh HD", "Time Machine Backups"} -- add as needed
property counter : 0
tell application "System Events"
set rootVolume to disk item (POSIX file "/Volumes" as text)
set allVolumes to name of every disk item of rootVolume
set StartTime to (get current date)
repeat with aVolume in allVolumes
if aVolume is not in ignoredVolumes then
set newName to "XXX" & counter as string
log newName & " in Progress... "
set name of disk item (path of rootVolume & aVolume) to newName
set counter to counter + 1
set scr to ("cp ~/USB-Stick/* /Volumes/" & newName)
do shell script scr
set name of disk item (path of rootVolume & newName) to "XXX"
do shell script "diskutil unmount /Volumes/XXX"
log newName & " finished."
end if
end repeat
set endTime to (get current date)
set dur to (endTime - StartTime)
display dialog "Process took " & dur & "seconds."
end tell
Hope this will helps other with the same problem.
Only one cosmetic problem: The call of the two shell scripts throws an error -10004 but still works. Tried with tell Application "Finder" or "Terminal" but error remains and has been added by other errors so i stick with my origin solution.
Kind Regards

Related

How do I get the properties or the info of a file using AppleScript?

I need to write the properties or at least the info of a file I have only the name of (here: "text2.txt") to a textfile.
I tried various ways but each time I just get the properties of the Desktop folder but not the file.
What am I doing wrong here?
try
tell application "Finder"
set this_folder to path of (folder of the front Finder window) as alias
end tell
on error
-- no open folder windows
set this_folder to path to desktop folder as alias
set is_desktop to true
end try
tell application "System Events"
set file_list to the name of every file of this_folder
end tell
tell application "Finder"
set theFile to path to desktop folder
set myList to {}
repeat with n from 1 to count of file_list
set currentFile to item n of file_list
set the_filePath to this_folder
set the_filename to currentFile
if currentFile contains "text2.txt" then
set {creation date:creaDate, modification date:modDate, name:fName, displayed name:dName, name extension:nExt, description:descript, URL:fPath} to properties of the_filePath
set theText to creaDate & "#" & modDate & "#" & fName & "#" & dName & "#" & nExt & "#" & descript & "#" & fPath
do shell script "echo " & theText & ">> $HOME/Desktop/FileProperties.txt"
end if
end repeat
end tell
I think you mostly have it right already.
Finder windows have a 'target', which is the folder that the window looks at. You can get and set the target normally. Everything below the try statement is unchanged.
try
tell application "Finder" to set this_folder to target of front window as alias
on error
set this_folder to (path to desktop) as alias
set is_desktop to true
end try
As alternatives, the script could use TextEdit or its own 'write' command to create the text document. If you're curious, let me know and I'll add those options.
Okay… here is a script you can try that should handle the writing within applescript. I've made a few other tweaks, all of which are commented (which unfortunately, make the script appear longer than it really is).
Applescript has a built-in 'File Read/Write suite' which you can read about each command in the Language Guide here, but in a nutshell, you use these commands to write to a new file, replace or append text to an existing file.
p.s. I changed some of your variable names
-- Make front window specifier a global var. Unnecessary if you integrate System Events block into Finder block (see below)
global fw
tell application "Finder"
try
set targFol to target of front window as alias
set fw to front window
on error
set targFol to (path to desktop) as alias
set fw to make Finder window to targFol
end try
end tell
The system events block below could also be handled by the Finder. If the folders you're rooting through don't typically have thousands of files in them (or if the alternative line is sufficient), you should consider doing so, as the primary advantage of using System Events is performance with high file counts. I don't think any changes would be required beyond removing the appropriate 'tell/end' statements.
tell application "System Events"
-- Some filtering options as an alternative to the repeat loop
set txFiles1 to files of targFol whose kind is "Plain Text Document"
set txFiles2 to files of targFol whose kind is "Plain Text Document" and name is "text2.txt"
set txFile to item 1 of txFiles2
-- Alternatively, you can just use the file itself, without any of the rigmarole.
set txFile to file "text2.txt" of targFol
end tell
tell application "Finder"
set {creation date:creaDate, modification date:modDate, name:fName, displayed name:dName, name extension:nExt, description:descript, URL:fPath} to properties of targFol
set newText to creaDate & "#" & modDate & "#" & fName & "#" & dName & "#" & nExt & "#" & descript & "#" & fPath as text
end tell
-- Write the properties as text to a text file -- requires the 'class furl' bit to work
set tf to (path to desktop as text) & "FileProperties.txt" as «class furl»
-- Alternatively, you could create the text file in the target folder
-- set tf to (targFol as text) & "FileProperties.txt" as «class furl»
close access (open for access tf)
write newText to tf as text
-- And some obvious things you can do with your new text file
tell application "TextEdit" to open tf
tell application "Finder" to select tf
set rtext to read tf
I made a few adjustments to your code. Maybe something like this will help you out.
property theFile : "text2.txt"
tell application "Finder"
try
-- Gets The Name Of The Front Finder Window If There Is One Opened
set containerName to name of front Finder window as POSIX file as text
-- Checks If The File "text2.txt" Exists In That Folder
-- fileExists Will Be Set To True Or False Depending On The Results
set fileExists to (containerName & theFile) as alias exists
on error errMsg number errNum
-- If Either Of The Previous Commands Throws An Error
-- This Will Give You An Option To Choose A Folder Where You Think
-- The File "text2.txt" Is Located
activate
set containerName to my (choose folder with prompt "Choose A Folder") as text
end try
try
-- Checks If The File "text2.txt" Exists In The New Chosen Folder
set fileExists to (containerName & theFile) as alias exists
on error errMsg number errNum
-- If "text2.txt" Does Not Exist In This Folder Either, Script Stops Here
return
end try
delay 0.1
-- If fileExists Is Set To True From Previous Commands
if fileExists then
set fullFilePath to (containerName & theFile) as alias
set {creation date:creaDate, modification date:modDate, name:fName, displayed name:dName, name extension:nExt, description:descript, URL:fPath} to properties of fullFilePath
set theText to creaDate & "#" & modDate & "#" & fName & "#" & ¬
dName & "#" & nExt & "#" & descript & "#" & fPath
tell current application to (do shell script "echo " & theText & ¬
">> $HOME/Desktop/FileProperties.txt")
end if
end tell

Apple script to export images from "Photos" application

I have albums and nested albums and folders in Photos application. I want my applescript to export images maintaining the Album or Folder structure that I have the in the application.
I tried scripts available online :
tell application "Finder"
set location_1 to (choose folder with prompt "Choose a folder to export into") as text
end tell
tell application "Photos"
set x to name of every folder
choose from list x with prompt "Choose a project to export"
set theP to item 1 of result
tell application "Finder" to make new folder at alias location_1 with properties {name:theP}
tell folder theP
set initflist to every folder
set initalist to every album
if initflist is equal to {} then
log "process albums"
processAlbums(initalist, location_1 & theP) of me
else
if initalist is not equal to {} then
log "process albums"
processAlbums(initalist, location_1 & theP) of me
end if
log "process sub folders "
processSfolders(initflist, (location_1 & theP)) of me
end if
end tell
end tell
on processAlbums(alist, apath)
tell application "Photos"
repeat with a in alist
tell a
set theimages to get media items of album a
set thename to name of a
tell application "Finder"
if not (exists folder thename in alias apath) then
make new folder at alias apath with properties {name:thename}
end if
set destination to apath & ":" & thename & ":"
end tell
with timeout of 6000 seconds
tell a
set settings to "JPEG - Original Size"
export theimages to alias destination
end tell
end timeout
end tell
end repeat
end tell
end processAlbums
on processSfolders(flist, fpath)
tell application "Photos"
repeat with a in flist
try
set thename to name of a
tell application "Finder"
if not (exists folder thename in alias fpath) then
make new folder at alias fpath with properties {name:thename}
end if
end tell
tell a
set sAlist to every album
set sflist to every folder
if sflist is equal to {} then
processAlbums(sAlist, fpath & ":" & thename) of me
else
if sAlist is not equal to {} then
processAlbums(sAlist, fpath & ":" & thename) of me
end if
processSfolders(sflist, fpath & ":" & thename) of me
end if
end tell
on error errMsg
log "error"
end try
end repeat
end tell
end processSfolders
The issue is that it gets names of only child albums and not top level albums. I have to maintain the entire structure of album or folder.
I do not know AppleScript and I tried tweaking this one but no luck so far. can I get a direction please?
You can get the name of the folders, and the albums contained in the folder, which will enable you to create the top level and child directories. Albums can only contain media items, not albums. Top level albums are classified as folders or containers. In the Applescript dictionary for Photos, it gives the definitions for these items.
tell application "Finder"
set location_1 to (choose folder with prompt "Choose a folder to export into") as text
end tell
tell application "Photos"
activate
set fds to folders
repeat with fd in fds
set fdName to name of fd
set abNames to every album of fd
if parent of fd is missing value then
my createFolders(fdName, abNames, location_1, fd)
end if
end repeat
end tell
on createFolders(fName, aAlbums, fPath, fd)
tell application "Finder"
if not (exists folder fName in alias fPath) then
make new folder with properties {name:fName} at fPath
end if
repeat with a in aAlbums
set aName to name of a
set aPath to ((fPath as alias) as text) & fName
if not (exists folder aName in alias aPath) then
make new folder with properties {name:aName} at aPath
end if
set exPath to ((aPath as alias) as text) & aName
my exportImages(a, exPath)
end repeat
end tell
tell application "Photos"
set rcFolders to every folder of fd
repeat with rcFd in rcFolders
set rcAlbums to every album of rcFd
set rcName to name of rcFd
set rcPath to ((fPath as alias) as text) & fName
my createFolders(rcName, rcAlbums, rcPath, rcFd)
end repeat
end tell
end createFolders
on exportImages(photoAlbum, destination)
tell application "Photos"
set theimages to get media items of photoAlbum
with timeout of 6000 seconds
tell photoAlbum
set settings to "JPEG - Original Size"
export theimages to alias destination
end tell
end timeout
end tell
end exportImages
EDIT - Error Handling
To handle errors, locate the command that is causing the error and wrap it in a try block. Solution could be to quit the application, so that the process will end, and maybe add a short delay and then continue with the script.
try
export theimages to alias destination
on error
-- statements to execute in case of error
error "The exporting of images failed to complete"
quit
end try
From the developer reference - When a command fails to complete in the allotted time (whether the default of two minutes, or a time set by a with timeout statement), AppleScript stops running the script and returns the error "event timed out". AppleScript does not cancel the operation—it merely stops execution of the script. If you want the script to continue, you can wrap the statements in a try statement. However, whether your script can send a command to cancel an offending lengthy operation after a timeout is dependent on the application that is performing the command. Further info regarding try statements.

Combining two (applescript) scripts into one

I'm trying to simplify my workflow by combining the following two applescripts into one, they work fine separately but it'd be more efficient to combine them.
In short, script A trims a file name into the last 3 characters and Script B adds the folder name (where the files reside) to the file name.
This might be a very simple fix but I'm script-writing challenged so any help is welcomed.
SCRIPT A:
on open whichFile
repeat with aFile in whichFile
tell application "Finder"
set filename to name of aFile
set name of aFile to ((characters -1 thru -7 of filename) as string)
--set name of whichFile to ((characters 1 thru -4 of filename) as string) --trim last 3
end tell
end repeat
end open
SCRIPT B
on open theDroppedItems
repeat with a from 1 to length of theDroppedItems
set theCurrentDroppedItem to item a of theDroppedItems
set theCurrentDroppedItem to theCurrentDroppedItem as string
tell application "System Events"
set folderPath to theCurrentDroppedItem as string
--display dialog (folderPath)
set AppleScript's text item delimiters to ":"
set newFileName to (text item -4 of folderPath as string) & "-" & (text item -2 of folderPath as string) & "-" & (text item -1 of folderPath as string)
--display dialog (newFileName)
--rename file
set fileAlias to (theCurrentDroppedItem) as alias
set the name of fileAlias to newFileName
end tell
end repeat
end open
You can start by opening a new Script Editor document for the combined script. The open handler is passed a list of file items, so you can add a new handler declaration with an empty repeat statement that steps through the dropped items. From there, just identify the statements that perform the various operations (trim name, get folder name, etc), and copy them into the new open handler's repeat statement, editing as needed to use consistent variable names.
Once the new script is running, then you can look at optimizing it by combining and/or rearranging statements that may be doing the same thing in the different scripts. It can also be helpful to organize functions into their own handlers, such as the getNamePieces handler below. I also like to add a run handler with a choose file dialog so that you can test without having to drag items onto a droplet.
Note that the file name includes any extension, so you should break it apart in order to work with just the name part. There is also a bit of unnecessary thrashing about in the script that gets the folder name, so after cleaning it up your script could look something like:
on run
open (choose file with multiple selections allowed)
end run
on open droppedItems
repeat with anItem in droppedItems
set {folderPath, theName, extension} to getNamePieces from anItem
set trimmedName to text -1 thru -3 of theName -- work with just the name part
tell application "System Events"
set folderName to name of disk item folderPath
set newName to folderName & "-" & trimmedName & extension -- assemble the pieces
log newName -- for testing
# set name of anItem to newName -- uncomment to go live
end tell
end repeat
end open
to getNamePieces from someItem -- return the containing folder path, the name, and the extension
tell application "System Events" to tell disk item (someItem as text)
set theContainer to path of the container
set {theName, extension} to {name, name extension}
end tell
if extension is not "" then
set theName to text 1 thru -((count extension) + 2) of theName -- just the name part
set extension to "." & extension
end if
return {theContainer, theName, extension}
end getNamePieces

Open Finder alias

I'm relatively new to Applescript, I was hoping someone can help me resolve this one...
I have a script that does a spotlight search and returns the found items as founditems. The result will either be a folder or an alias to a folder. I'd like to open the found item and it works if the result is a folder but I can't figure how to handle an alias. With an alias I get the error incorporated in the code
try
set theapp to default application of (get info for (POSIX file founditems)) as string
tell application theapp to open (POSIX file founditems as string)
activate application theapp
on error e
display dialog "An error has occured trying to open your file:" & return & return & e buttons {"OK"} default button 1
end try
I get 10665 error code. My guess is that incorporating original path may resolve the alias issue but I'm not sure how to plug it in... Thanks much
founditems is created this way:
set input_var to "12345"
set spotlightquery to "\"kMDItemFinderComment == '" & input_var & "'\""
set thefolders to {POSIX file "/Volumes/RAIDvolume"}
set founditems to {}
repeat with i in thefolders
set thepath to quoted form of POSIX path of i
if exists thepath then
set command to "mdfind -onlyin " & thepath & " " & spotlightquery
set founditems to founditems & (paragraphs of (do shell script command))
end if
end repeat
So it was a list because you used "paragraphs of" and I can see now that founditems is a list of posix paths. As such the following will open it with the default application regardless if the path is to a file, folder or alias.
set founditems to {"/Users/hmcshane/Desktop/aaa alias"}
set macPath to POSIX file (item 1 of founditems)
tell application "Finder" to open macPath

AppleScript: Create new folder from file name and move file into that folder

Basically, I'm trying to create a folder action in Automator so whenever a file is added to a specific folder, it will create a subfolder that matches the filename (without the extension), then move the file into that subfolder.
So far, I have successfully used a post from this site (Create new folder named with a specified file name in Automator) to create a script that will create the new folder. However, I have been unable to modify the script to move the original file into the new folder.
Any help would be appreciated. Here is the full script I am working with for reference:
on run {input, parameters} -- make new folders from base file names
set output to {}
repeat with anItem in the input -- step through each item in the input
set anItem to anItem as text
tell application "System Events" to tell disk item anItem
set theContainer to path of container
set {theName, theExtension} to {name, name extension}
end tell
if theExtension is in {missing value, ""} then
set theExtension to ""
else
set theExtension to "." & theExtension
end if
set theName to text 1 thru -((count theExtension) + 1) of theName -- the name part
tell application "Finder"
make new folder at folder theContainer with properties {name:theName}
set end of output to result as alias
end tell
end repeat
return input -- or output
end run
Thanks in advance!
Add this folder action to your target folder:
on adding folder items to theFolder after receiving theFiles
repeat with aFile in theFiles
tell application "System Events" to set {Nm, Ex, pPath} to aFile's {name, name extension, POSIX path of container}
set BN to text 1 thru ((get offset of "." & Ex in Nm) - 1) of Nm
set thePath to (pPath & "/" & BN & "/" as text)
do shell script "mkdir -p " & quoted form of thePath
delay 0.5
tell application "Finder" to move aFile to POSIX file thePath
end repeat
end adding folder items to

Resources