Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

j.tan

macrumors newbie
Original poster
Jul 29, 2024
5
0
I’m new to AppleScript, and have been writing a script to prepend the current date to an existing file or folder name. The script appears to work well, except for a very specific instance. When using the script to rename a single text file (i.e. a file with the ‘.txt’ extension) on Mac OS Sonoma 14.5, Finder hangs with spinning beachball, requiring a relaunch. The file in question remains unchanged i.e. the script does not completely execute.

Running the script does not trigger the same issue under these conditions:
  • Using more than one .txt file i.e. it works fine when two or more .txt files are selected in Finder.
  • Using multiple files or a mix of files and folders, with a single .txt file in the selection.
  • Using files of types other than .txt (e.g. .jpg, .pdf, .workflow, etc.), single or otherwise.
  • On a folder with ‘.txt’ added to the end of the folder name.
  • On a file of a different type e.g. .jpg that has had its extension changed to .txt (with corresponding warning from Finder about changing file extensions).
  • On Mac OS Ventura 13.6.7 i.e. no problem at all, even with single .txt files. I haven’t tested on other versions of Mac OS.
Here is a simplified bit of code (minus date handling, date formatting, etc.) that replicates the issue on my side:

AppleScript:
activate application "Finder"

set prependText to "xyz "

tell application "Finder"
    set theSelection to the selection
    repeat with anItem in theSelection
        set currentName to name of anItem
        set newName to prependText & currentName
        set name of anItem to newName
    end repeat
end tell

Are any of you able to replicate the problem? Any idea what’s going on?
 
Works for me on macOS Sonoma 14.5 (Apple Silicon).
test.txt > xyz test.txt
Could it be an issue with permissions or access to that specific file?
Did you try it with a newly created file?
Does Finder also hang when you add a try
AppleScript:
repeat with anItem in theSelection
    try
        (...)
    end try
end repeat
 
  • Like
Reactions: j.tan
Thanks for giving it a go and replying so quickly. That’s interesting. I did try with various .txt files, but they were all copies of existing ones. Permissions seemed fine, but I didn’t dig into that too deeply.

I’ll try your suggestions when I’m next at my Sonoma workstation, and maybe also try with a newly-created user account.
 
Last edited:
Posting a working script that doesn't use a date isn't going to help much - since the issue seems to be related to the prefix, how exactly are you getting the prefix string?
 
I’ve tried creating a new text file and with a fresh user account, but the problem persists. Using a ‘try’ block doesn’t help either. However, and interestingly, I’ve discovered that the issue only comes up if selecting a single .txt file in Column or Gallery view i.e. no problem if running the script on the file when View is set to ‘as Icons’ or ‘as List’.

@arw If you haven’t already done so, do you mind trying again with a single .txt file and using View>as Columns (⌘ 3) and/or View>as Gallery (⌘ 4)?

@Red Menace I actually wrote the simplified script as a debugging tool to try to isolate the issue, that is to see if the date handling / formatting had anything to do with it. The issue can be replicated without the date part, which suggests that the issue is not related to the prefix or the date code. In other words, it seems to me that it’s the renaming part that triggers the hang (which does not absolutely rule out the date handling at this stage, of course). With that in mind, I thought it might be less distracting and perhaps more useful if I just posted the simplified code.
 
Last edited:
If you haven’t already done so, do you mind trying again with a single .txt file and using View>as Columns (⌘ 3) and/or View>as Gallery (⌘ 4)?
Wow it actually freezes Finder. Great observation! (As well as a greatly written description of your main question, if I might say.)
I did some testing and if I enable the 'preview pane' (⇧⌘P) in 'as Icons' or 'as List', it also freezes Finder.
The common demoniator is, it fails when Finder is showing a scrollable preview of a text file. This isn't the case for more than one file as Finder then only displays rendered still images.

I'd report it as a bug via Apple's feedback.

EDIT: Ignore the following and head to the next post.

In the meantime (or as a proof of concept) I modified your script:
If it detects macOS Sonoma and only a single .txt file has been selected, it performs two checks:
- If the view is 'as Gallery', it temporarily switches to 'as List'. This has to be done as the scrollable preview is not displayed in the optional 'preview pane' but in the main window, so it always fails.
- It then checks if the 'preview pane' is active in the current Finder view and disables it for the time of the rename operation.
(Using the keystroke command requires 'Accessibillity' permissions.)

AppleScript:
activate application "Finder"

set prependText to "xyz "
set versionString to system version of (system info) -- get version of macOS
set finderView to (do shell script "defaults read com.apple.finder FXPreferredViewStyle") -- get type of view
set previewState to (do shell script "defaults read com.apple.finder ShowPreviewPane") -- check if PreviewPane is enabled

tell application "Finder"
    set theSelection to the selection
    -------------------------------
    set numberOfItems to count of theSelection
    if numberOfItems is 1 and name of first item of theSelection ends with ".txt" and versionString begins with "14." then
        if finderView is "glyv" then -- 'glyv' means 'GalleryView'
            my setViewToList()
            set previewState to (do shell script "defaults read com.apple.finder ShowPreviewPane") -- re-evaluate previewState for 'List view'
            if previewState as string is "1" then
                my togglePreview()
                delay 1
                my renameRoutine(prependText, name of first item of theSelection, first item of theSelection)
                my togglePreview()
            else
                my renameRoutine(prependText, name of first item of theSelection, first item of theSelection)
            end if
            my setViewToGallery()
        else
            if previewState as string is "1" then
                my togglePreview()
                delay 1
                my renameRoutine(prependText, name of first item of theSelection, first item of theSelection)
                my togglePreview()
            end if
        end if
    else
        -------------------------------
        repeat with anItem in theSelection
            set currentName to name of anItem
            my renameRoutine(prependText, currentName, anItem)
        end repeat
    end if
end tell

on renameRoutine(prependText, currentName, anItem)
    set newName to prependText & currentName
    set name of anItem to newName
end renameRoutine

on setViewToList()
    tell application "System Events" to tell process "Finder" to keystroke "2" using {command down}
end setViewToList

on setViewToGallery()
    tell application "System Events" to tell process "Finder" to keystroke "4" using {command down}
end setViewToGallery

on togglePreview()
    tell application "System Events" to tell process "Finder" to keystroke "P" using {command down, shift down}
end togglePreview
 
Last edited:
  • Like
Reactions: Alameda and j.tan
That is weird. Another option would be to just use Finder to get the selection, and System Events for everything else:

AppleScript:
activate application "Finder"

set prependText to "xyz "

tell application "Finder" to set theSelection to the selection as alias list
tell application "System Events" to repeat with anItem in theSelection
   set currentName to name of anItem
   set name of anItem to (prependText & currentName)
end repeat
 
Last edited:
  • Like
Reactions: j.tan and arw
Nice, that is definitely the proper way to handle the issue. Now I'm ashamed of my Frankenstein workaround 🙈
Well, I learned something new today.
 
  • Like
Reactions: j.tan
Thanks @arw and @Red Menace for your contributions – I really appreciate it. I’ve certainly learned a few things as well.

Interestingly (or perhaps obviously?), using the ‘tell application System Events’ method freezes Finder again if not using alias list (i.e. setting ‘theSelection’ to the selection), and conversely, using the ‘tell application Finder’ method still freezes Finder if using alias list (and a single .txt file for both cases).

My own research so far tells me that calling System Events to perform operations like this is generally more resource-efficient than calling Finder, but might require additional permissions requests / approval from the user (such as when I experienced when trying @Red Menace ’s code), and can be a bit more complex or less intuitive to code. Is there anything that either of you may care to add to this (i.e. when to use System Events vs Finder, and vice versa)?
 
I tend to use System Events more often, as it supports POSIX paths without jumping through additional hoops, but there are some things that Finder provides, such as selections in its windows. System Events provides a lot more functionality than just file and folder stuff though, while Finder mostly puts a user interface on the file and folder stuff, as it is essentially the face of macOS. There is some overlap, as they both use some of the same underlying APIs to provide some similar functionality.

You do need to pay attention to the scripting terminology that any given application provides, as it is entirely up to the developer, and similar terms don't necessarily exist or mean the same thing. For example, System Events does not have a selection (it is a background app without a UI), and Finder typically returns its own kind of file references that are not usable by others, so alias list coerces them to something more standard.

For my answer, since Finder can get the selection without hanging, and System Events can rename without issue because it doesn't have anything to do with Finder windows, a combination seemed like the way to go. I've done the same thing in some of my apps - use scripting to get the current Finder selection, and the Cocoa API for everything else.
 
  • Like
Reactions: arw and j.tan
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.