Open All Items in Preview's "Open Recent" Menu

Sometimes, for whatever reason, applications don't reopen previously-open files, even when that option is selected in System Preferences.

In Preview, the menu item for 'recently open files' is File --> Open Recent. I would like to automate re-opening all of the files in that submenu.

I think the following approach will work, though it's not the most elegant, efficient, or robust solution:

[Note that opening any item in the "Open Recent" submenu brings that item to the top of the list in that same submenu.]

  1. Show Menu "Open Recent" in the Menu "File" in Preview

  2. Type the 'Option + Down Arrow' Keystroke (jumps to last item in list)

  3. Type the Up Arrow Keystroke (the last item is always "Clear Menu"; we want the item immediately above "Clear Menu")

  4. Type the Return Keystroke (this opens the selected item)

  5. Loop all of the above as many times as there are items in the menu.

Questions:

  1. Do I need any pauses in the macro? For example, before each loop cycle to give Preview time to open the file?

  2. The last item in the "Open Recent" submenu is "Clear Menu." For obvious reasons, I want to avoid ever clicking that in the context of this macro. Is there a way to add a test before the Return keystroke to ensure that "Clear Menu" is not selected?

  3. Is there a way to dynamically determine the number of items available in the submenu, and to loop the macro that many times?

  4. Surely there is a more efficient way of doing this, but I don't know what that way is. Ideas?

Thank you.

Hey There,

Not with Keyboard Maestro per se, but you can run an AppleScript UI-Script from KM.

See ⇢ Execute an AppleScript action.

This script works on Mojave. I can't speak for other versions of macOS.

It should be adaptable to most normal macOS applications.

-Chris


--------------------------------------------------------
# Auth: Christopher Stone
# dCre: 2021/10/30 19:17
# dMod: 2021/10/30 19:17 
# Appl: Preview, System Events
# Task: Open All Recent Items Listed in the Recent Items Menu.
# Libs: None
# Osax: None
# Tags: @Applescript, @Script, @Preview, @System_Events, @Open, @Recent, @Items
# Test: Tested only on macOS 10.14.6.
--------------------------------------------------------

tell application "System Events"
   tell application process "Preview"
      tell menu bar 1
         tell menu "File"
            tell menu item "Open Recent"
               tell menu 1
                  set recentMenuItems to UI elements whose title is not "Clear Menu" and title is not ""
                  
                  repeat with menuItem in recentMenuItems
                     tell menuItem
                        perform action "AXPress"
                     end tell
                  end repeat
                  
               end tell
            end tell
         end tell
      end tell
   end tell
end tell

--------------------------------------------------------
2 Likes

Thank you, Chris!

Any chance you can help me to expand the functionality of your script? Rather than having the script open all items in "Open Recent," I would like to be able to select items to open from a list of the "Open Recent" items.

I took a stab at cobbling together a solution, but no dice. And since I have minimal idea what I'm doing, troubleshooting is tough :stuck_out_tongue:

(Note that my attempt was with Finder's "Recent Folders" rather than Preview's "Open Recent." My probably-mistaken assumption is that I can switch between them with a few obvious word changes.)

tell application "System Events"
tell application process "Finder"
	tell menu bar 1
		tell menu "Go"
			tell menu item "Recent Folders"
				tell menu 1
					set recentMenuItems to {UI elements whose title is not "Clear Menu" and title is not ""}
						set selectedFiles to choose from list recentMenuItems with multiple selections allowed
					if selectedFiles is false then return
					repeat with aFile in selectedFiles
					tell application "Finder" to open file aFile
					end tell
					end repeat
				end tell
			end tell
		end tell
	end tell
end tell
end tell

Which, as you probably know, doesn't work. Fingers crossed.

Happy new year!

1 Like

I reckon...

--------------------------------------------------------
# Auth: Christopher Stone
# dCre: 2022/01/03 06:42
# dMod: 2022/01/03 06:42 
# Appl: Finder, System Events
# Task: Use a Pick List to Choose One or More Recent Folders to Open.
# Libs: None
# Osax: None
# Tags: @Applescript, @Script, @Finder, @System_Events, @Pick, @List, @Choose, @Open, @Recent, @Folders
--------------------------------------------------------

tell application "System Events"
   
   tell application process "Finder"
      set frontmost to true
      
      tell menu bar 1
         tell menu "Go"
            tell menu item "Recent Folders"
               tell menu 1
                  set recentMenuItemNames to name of menu items whose title is not "Clear Menu" and title is not ""
                  
                  tell application "Finder"
                     set userPickList to choose from list recentMenuItemNames with title ("Recent Folders") ¬
                        with prompt ("Choose One or More Recent Folders:") ¬
                        default items {item 1 of recentMenuItemNames} ¬
                        with multiple selections allowed
                  end tell
                  
                  repeat with recentFolderName in userPickList
                     tell (first menu item whose name is recentFolderName)
                        perform action "AXPress"
                     end tell
                  end repeat
                  
               end tell
            end tell
         end tell
      end tell
      
   end tell
end tell

--------------------------------------------------------
2 Likes

Thank you! I am happy to report that with only the obvious modifications, it works in Preview as well.

Pushing my luck here, is there a way to exclude from the list those menu items that are not currently available? If not, is there a way to have the script continue even if it encounters an error opening one or more menu items? :crossed_fingers:

I appreciate your help!

No. The menu item does not give access to the file it's associate with (shame on Apple for that).

Try this:

--------------------------------------------------------
# Auth: Christopher Stone
# dCre: 2022/01/03 06:42
# dMod: 2022/01/05 04:41
# Appl: Finder, System Events
# Task: Use a Pick List to Choose One or More Recent Folders to Open.
# Libs: None
# Osax: None
# Tags: @Applescript, @Script, @Finder, @System_Events, @Pick, @List, @Choose, @Open, @Recent, @Folders
# Vers: 1.01
--------------------------------------------------------

tell application "System Events"
   
   tell application process "Finder"
      set frontmost to true
      
      tell menu bar 1
         tell menu "Go"
            tell menu item "Recent Folders"
               tell menu 1
                  set recentMenuItemNames to name of menu items whose title is not "Clear Menu" and title is not ""
                  
                  tell application "Finder"
                     set userPickList to choose from list recentMenuItemNames with title ("Recent Folders") ¬
                        with prompt ("Choose One or More Recent Folders:") ¬
                        default items {item 1 of recentMenuItemNames} ¬
                        with multiple selections allowed
                  end tell
                  
                  repeat with recentFolderName in userPickList
                     tell (first menu item whose name is recentFolderName)
                        try
                           perform action "AXPress"
                        end try
                     end tell
                  end repeat
                  
               end tell
            end tell
         end tell
      end tell
      
   end tell
end tell

--------------------------------------------------------
2 Likes

Hi Chris @ccstone ,

Thanks for your provocative script. I had no idea that AppleScript's chose from list ... with multiple selectons allowed existed. But it won't work for me unless I can export that userPickList as a list of filenames.

I'm trying to understand your comment and your creation of userPickList above and I'm a bit confused. Does this mean that the list you create consists of "menu items" and not file names? And that there is no way to get the file name from the menu item other than opening it?

I would like to turn the entire File > Recent Files list into a Prompt With List so that I can do things with the file or filename before and after opening it.

Having to open the file from the menu in order to get its filename would be unacceptable overhead. Any ideas?

Hello August (@August),

Just a quick reply here from me - even that I’m not Chris …

First it’s worth to have the Full Commands Reference of the StandardAdditions.osax -which comes with the OS - saved any where else as a go to … It gives you everything you need to now about every single command.

Below is an old AppleScript Snippet I just found in my Snippets Database - maybe it works right out of the box but I can not give you a guarantee. It maybe needs some tweaking…

With it you can get the Items and their associated Paths of the Recent Folders Menu of the Go Menu in the Finder


on findPathSeparator(theData, theFile)
    set pathSeparator to {0, 0, 0, 1, 1, 0, 0}
    set bytesFound to 0
    set bytesSearched to 0

    try
        read theFile from 0 for 0

        set numIterations to 0

        repeat (get eof theFile) times
            set theId to id of (read theFile from bytesSearched for 1)

            if theId is item (bytesFound + 1) of pathSeparator then
                set bytesFound to bytesFound + 1
            else
                set bytesFound to 0
            end if

            if bytesFound is (count of pathSeparator) then exit repeat

            set bytesSearched to bytesSearched + 1
        end repeat
    on error msg
        msg
    end try

    return bytesSearched - (count of pathSeparator)
end findPathSeparator

on getPathFromData(theData)
    set pathSeparator to {0, 0, 0, 1, 1, 0, 0}

    set theFile to (open for access POSIX file ("/tmp/get_recent_folders") with write permission)

    set eof theFile to 0

    write contents of theData to theFile

    set startPosition to findPathSeparator(theData, theFile)

    try
        read theFile from startPosition for 0

        set thePath to ""

        repeat
            set idList to id of (read theFile for 8)

            if (idList does not end with pathSeparator) then exit repeat

            set theLength to item 1 of idList

            set thePath to thePath & ("/" & (read theFile for theLength as «class utf8»))

            read theFile for (4 - theLength mod 4) mod 4
        end repeat
    on error msg
        msg
    end try

    close access theFile

    return thePath
end getPathFromData

tell application "System Events"
    tell property list file "~/Library/Preferences/com.apple.finder.plist"
        set dataItems to property list item "FXRecentFolders"'s property list items's property list item "file-bookmark"'s value
        set itemNames to property list item "FXRecentFolders"'s property list items's property list item "name"'s value
    end tell
end tell

set theOutput to ""

set itemNum to 1
repeat (count of dataItems) times
    set theOutput to theOutput & item itemNum of itemNames & "
" & getPathFromData(item itemNum of dataItems) & "
"
    set itemNum to itemNum + 1
end repeat

theOutput

While I am currently not able to test anything out you will have to deal with it on your own but if you are able to get it working and format the output to your liking you should be able to crate a Prompt with List based Macro from it.

Let us now how it goes

Greetings from Germany :de:

Tobias

Thanks Tobias! (And no need to apologize for not being Chris! I will accept help from anyone.)

That looks, as far as I can read it so far, and from your description, very useful.

I am sure that I will have questions about multiple layers of this. I hope you remember something of how it works. There are definitely, already, things that I don't understand what the do or why you would do that. But I'll wait to ask until I have had more time to read through it. That won't be for a few days.

It looks like you are somehow parsing paths out of data in a Finder plist file. Cool. I appreciate that head start. I will be working with TextEdit's saved data instead of Finder, but I hope it will be similar.

Thank you very much!

This is not the solution I'm looking for. In the OP, @passwordisburrito says

That's what I had been counting on, and that doesn't work for me.

Previously I had the mistaken idea, confirmed by the OP, that the "Recent Files" list in an application was sorted in reverse chronological order, with the most recent at the top. It turns out that (at least for TextEdit) the order is "most recent opened", not most recent accessed, which is what I want. It doesn't work to open a file that's already opened. I can pick a file from this list, which is called "Open Recent" and the fact that I opened that particular file does not affect the order of the list. Nor does using the KBM action to "Open a File, Folder, or Application". If the file is already open, opening it again does not affect the "Open Recent" list.

Unfortunately, the shell command, $ ls -ltu is not useful either. When I use it, I see nearly every file in the folder accessed in the same minute, initially about five minutes ago, and then staying the same as I explore it. I haven't been able to figure out what accessed all those files, but it certainly wasn't me doing it manually.

Maybe I just have to maintain my own list. That's a bit of a pain, but if the OS won't do it for me, what else do I have?

So, to create my own "most recently accessed list", does anyone have a KBM list manipulation macro that will find an element in a list and pop it to the top or bottom of the list?

I suppose to manipulate the Recently Opened list I could simply close the file and immediately reopen it again, every time. I would hope that that would get the list into the order that I am looking for. But I'd rather not.