I want to tell the Finder to duplicate an item under another name.
or some other way to do this.
I don’t mean to rename the item first. But save it under another name.
In AppleScript Studio there is this nice “save Panel” feature but is does not actually save.
In plain applescript, you can use the ‘choose file name’ command of the standard additions. This will give you a valid file reference, which can then be used to write a file. For example…
set oldPath to choose file
set oldContents to (read oldPath) as string
set newPath to choose file name with prompt "Save file as..."
open for access newPath with write permission
set eof of newPath to 0
write (oldContents) to newPath starting at eof
close access newPath
Regardless of whether you’re in plain AS or in studio, you’re still probably going to have to provide all of your own file writing routines. You will usually have to gather a path from the user (in a choose file name or save panel) and then manually write the file. Fortunately, writing a simple file is pretty straight-forward, so the approach above is pretty easy to implement.
There are a lot of ways to skin a cat (origin of that phrase, anyone?). For doing a simple duplication and rename you’ve got to extract the components of the save name (i.e., the folder and the name itself). Once you have that, just duplicate the file and rename using the Finder in one step (I added a little more so the new name already has the proper extension):
More than one method to reach the same end, as in We can get around that by renting instead of buying a computer—there’s more than one way to skin a cat. This expression may be an American version of the earlier British more ways of killing a cat, but why the death of a cat should be alluded to at all is not clear. [Second half of 1800s]"
The American Heritage® Dictionary of Idioms by Christine Ammer.
Unfortunately it is not a solution for my actual problem because this way, the name of the item to copy, may not exist in the output-Folder.
I experienced that the tell-Finder command translated into two commands: first copy and then set name.
I had to create another workaround for this problem. It is not very pretty and much to complicated for such a simple action as 'save as". And it is not completely Applescript error-proof.
In fact, it is not at all what I want. (I think the Finder should have a “save as” command in its dictionary.)
I am going to use it in an AppleScript Studio project. A batch-copy procedure with occasional messages if an item already exists. Then the user should be able to choose from 4 options: Cancel, skip, save-as and overwrite.
(*
Save as...
This script duplicates a chosen file to the same or another location.
If the name already exists, the file will be saved as: "inputName copy", "inputName copy 1" etc.
*)
property temporaryName : "*Some*Name*That*Is*Unlikely*to*Exist*"
set inputPath to (choose file with prompt "Choose a file to copy" without invisibles) as string
set OutputFolder to (choose folder with prompt "Choose a destination folder") as string
set infoList to ((info for (file inputPath)) as list)
set theExtension to item 8 of infoList
set extensionHidden to item 9 of infoList
set theName to item 14 of infoList
log theExtension
if (theExtension = missing value) or (theExtension = "") then
set theExtension to ""
set temp to theName
else
set theExtension to "." & theExtension
if extensionHidden then
set temp to theName
set theName to theName & theExtension
else
set temp to ""
set x4 to (length of theName)
repeat with x4 from x4 to 1 by -1
if character x4 of theName = "." then
set temp to characters 1 thru (x4 - 1) of theName as string
log temp
exit repeat
end if
end repeat
end if
end if
log "Name without extension = " & temp
set newName to theName
set existPath to OutputFolder & theName as string
set copyName to ""
set answer to true
set nbr to 0
repeat
tell application "Finder"
exists item existPath
set answer to result
end tell
if answer = false then
if not copyName = "" then
set newName to newName & theExtension
end if
exit repeat
end if
if nbr = 0 then
set copyName to " copy" as string
else
set copyName to (" copy " & nbr) as string
end if
set newName to temp & copyName as string
set existPath to OutputFolder & newName & theExtension as string
set nbr to nbr + 1
end repeat
log " newName = " & newName
set x3 to (length of inputPath)
set x4 to x3
repeat with x3 from x3 to 1 by -1 --> Replace the original name temporarily with 'temporaryName'
if character x3 of inputPath = ":" then
set tempPath to characters 1 thru x3 of inputPath & temporaryName as string
exit repeat
end if
end repeat
tell application "Finder"
set lock to locked of item inputPath
if lock = true then
set locked of item inputPath to false
end if
set saveName to name of item inputPath
set name of item inputPath to temporaryName
duplicate item tempPath to folder OutputFolder
set outputPath to result as string -- Needed when the item is duplicated in the same folder
log "result = " & outputPath
set name of item tempPath to saveName -- Undo the temporary name-Change.
set name of item outputPath to newName
if extensionHidden = true then
set extension hidden of item (OutputFolder & newName as string) to true
end if
if lock = true then
set locked of item inputPath to true
set locked of item (OutputFolder & newName as string) to true
end if
end tell
Thanks for the idea and please let me know if there is a better/safer/easier way to archive this.
In this topic and other topics that address “Save As”, thanks to a lot of leads from this BBS, I have developed the following (rather long) for GraphicConverter that may help others:
property allowedImageTypes : {"JPEG", "GIF", "PNG"}
property defaultSaveImageType : "JPEG"
property newSaveFolder : false
property defaultSaveFolderName : "Trimmed Images"
property defaultSaveFolderLocation : path to the desktop folder
global saveFolderLocation -- either where the image lives or where the above newbie lives
property trimFileSuffix : " [TRIM]"
global trimmedFileName -- = name + " [TRIM]" or name + ".JPEG [TRIM]"
-- for double-clicking an application
tell application "Finder"
activate
try
my hideOtherApps()
my makeSaveFolder()
set theImages to ¬
choose file with prompt "Select images to change their sizes." of type allowedImageTypes ¬
with multiple selections allowed without invisibles
my doGraphicConverter(theImages)
on error errorNbr
display dialog errorNbr
end try
end tell
-- for a droplet
on open (theImages)
tell application "Finder"
activate
try
my hideOtherApps()
my makeSaveFolder()
my doGraphicConverter(theImages)
on error errorNbr
display dialog errorNbr
end try
end tell
end open
on hideOtherApps()
-- Cmd-Option-H
tell application "Finder" to ¬
set visible of every process whose visible is true and name is not "Finder" to false
end hideOtherApps
on makeSaveFolder()
if newSaveFolder then
tell application "Finder"
set saveFolderLocation to defaultSaveFolderLocation as string
if (not (exists the folder defaultSaveFolderName in folder saveFolderLocation)) then
make new folder in folder saveFolderLocation ¬
with properties {name:defaultSaveFolderName}
end if
set saveFolderLocation to folder defaultSaveFolderName ¬
in folder saveFolderLocation as string
-- display dialog saveFolderLocation
end tell
else
-- saveFolderLocation set within getImageInfo(theImage)
end if
end makeSaveFolder
on getImageInfo(theImage)
tell application "Finder"
if (not newSaveFolder) then
-- in this case, each of multiple images will call this, for a minor speed bump
set saveFolderLocation to container of the theImage as string
end if
set imageFileName to name of theImage
set imageFileType to file type of theImage
if (imageFileType ≠defaultSaveImageType) then
set imageFileTypeSuffix to "." & defaultSaveImageType
else
set imageFileTypeSuffix to ""
end if
-- = name + " [TRIM]"
-- or if not a JPEG file
-- = name + ".JPEG [TRIM]"
set trimmedFileName to imageFileName & imageFileTypeSuffix & trimFileSuffix
end tell
end getImageInfo
on saveImageFile()
tell application "GraphicConverter"
save front window in (saveFolderLocation & trimmedFileName) as defaultSaveImageType
end tell
end saveImageFile
on startupGraphicConverter()
tell application "System Events"
if "GraphicConverter" is not in name of processes then
launch application "GraphicConverter"
end if
activate application "GraphicConverter"
delay 2 -- just a tad to give time for a front window to appear
end tell
end startupGraphicConverter
on doGraphicConverter(theImages)
startupGraphicConverter()
repeat with eachImage in theImages
getImageInfo(eachImage)
tell application "GraphicConverter"
open eachImage
tell front window
trim
copy image dimension to {imageWidth, imageHeight}
-- display dialog ("width = " & imageWidth & return & "height = " & imageHeight)
copy resolution to {resX, resY}
-- display dialog ("resX = " & resX & return & "resY = " & resY)
-- note that for ≥ 4.0", graphic is scaled down
-- and for < 4.0", graphic is scaled up
-- e.g., one JPEG has size = 3.90" x 2.69" = 702 pixels x 484.2 pixels
-- another has size = 5.90" x 4.43" = 1062 pixels x 797.4 pixels
-- and one has size = 5.12" x 8.57" = 921.6 pixels x 1542.6 pixels
--
-- so, for 1st, scaled = - 0.02564102564102564
-- scale = 1.02564102564102564
-- for 2nd, scaled = 0.1525423728813559
-- scale = 0.8474576271186441
-- for 3rd, scaled = 0.2998833138856475
-- scale = 0.7001166861143525
if (imageWidth ≥ imageHeight) then
if (imageWidth ≥ 6 * resX) then
set scaled to (imageWidth - 6 * resX) / imageWidth
else if (imageWidth ≥ 5 * resX) then
set scaled to (imageWidth - 5 * resX) / imageWidth
else if (imageWidth ≥ 4 * resX) then
set scaled to (imageWidth - 4 * resX) / imageWidth
else if (imageWidth ≥ 3 * resX) then
set scaled to (imageWidth - 4 * resX) / imageWidth
else if (imageWidth ≥ 2 * resX) then
set scaled to (imageWidth - 3 * resX) / imageWidth
else if (imageWidth ≥ 1 * resX) then
set scaled to (imageWidth - 2 * resX) / imageWidth
else
set scaled to (imageWidth - 2 * resX) / imageWidth
end if
else -- imageHeight > imageWidth
if (imageHeight ≥ 6 * resY) then
set scaled to (imageHeight - 6 * resY) / imageHeight
else if (imageHeight ≥ 5 * resY) then
set scaled to (imageHeight - 5 * resY) / imageHeight
else if (imageHeight ≥ 4 * resY) then
set scaled to (imageHeight - 4 * resY) / imageHeight
else if (imageHeight ≥ 3 * resY) then
set scaled to (imageHeight - 4 * resY) / imageHeight
else if (imageHeight ≥ 2 * resY) then
set scaled to (imageHeight - 3 * resY) / imageHeight
else if (imageHeight ≥ 1 * resY) then
set scaled to (imageHeight - 2 * resY) / imageHeight
else
set scaled to (imageHeight - 2 * resY) / imageHeight
end if
end if -- else (imageHeight > imageWidth)
-- display dialog scaled as string
scale horizontal (1 - scaled) vertical (1 - scaled)
end tell -- front window
my saveImageFile()
end tell -- application "GraphicConverter"
end repeat -- with eachImage in images
end doGraphicConverter