MacOS – Duplicating and renaming Finder selection to the same folder in one clean step

applescriptbashfindermacosterminal

Is such a thing possible? I have this code which can do the above:

set now to do shell script "date +%Y-%m-%d' '%H.%M.%S"
tell application "Finder"
    set finderSelList to selection as alias list
    try
        set fileDir to parent of first item of finderSelList as alias
    on error
        return "No selection"
    end try

    set dupeList to (duplicate finderSelList to fileDir) as list

    repeat with i from 1 to (count of dupeList)
        set ((dupeList)'s (item i)'s name) to ((finderSelList)'s (item i)'s name) & " [" & now & "]." & ((finderSelList)'s (item i)'s name extension)
    end repeat
end tell

return dupeList

However, it's not so clean—that is, you can see that the files' duplicates are named <file name> 2.<file extension>, and then a second later gets named to <file name> [date].<file extension>, which is pretty jarring to see.

I have a bash solution that is clean (i.e. not jarring), but using Finder to copy files has some benefits (like progress bars, cancelling copy operations, different xattr handling, etc.):

finderSelection=$(osascript getfinderselection.scpt)

now=$(date +%Y-%m-%d' '%H.%M.%S)

if [ "$finderSelection" ]
    then
    echo "$finderSelection" |
    while IFS= read -r file
    do
        fileDir=$(dirname "$file")
        fileBaseN=$(basename "$file")
        fileName="${fileBaseN%.*}"
        fileExt="${fileBaseN##*.}"

        cp -r "$file" "$fileDir/[$now] $fileName.$fileExt"
    done

    afplay "/System/Library/Components/CoreAudio.component/Contents/SharedSupport/SystemSounds/system/Volume Mount.aif"

fi

…and getfinderselection.scpt contains:

tell application "Finder"
    set finderSelList to selection as alias list
end tell

if finderSelList ≠ {} then
    repeat with i in finderSelList
        set contents of i to POSIX path of (contents of i)
    end repeat

    set AppleScript's text item delimiters to linefeed
    finderSelList as text
end if

In this implementation, when bash duplicates the files, you don't see any intermediate step wherein files are being renamed. No—when the duplicates spawn, their file names are already finalized.

So…

  • Is there a way to implement the idea in AppleScript but have it not so jarring and much more smooth, like how bash does it?
  • In the first place, should I run with the AppleScript solution or the bash one?
  • How else can the preferred solution be improved on? For the AppleScript solution, I need to find a way to remove the file extension from ((finderSelList)'s (item i)'s name), and also remove the trailing . when dealing with folders. For the bash solution, the fileName and fileExt outputs, especially for folders, can be unexpected and messy.

Best Answer

For your applescript solution, you could duplicate to a temporary directory (preferably on the same file system), then rename them back to the original directory. I tried to hack this together for you but gave up...

If you want an alternative, instead of bash you might look into this answer https://stackoverflow.com/a/275945/1942837 which provides a (presumably) nice python gui with progress (I have not tested this).