Writing "data" type values to a pList / Pages Recent Docs

I am writing an applescript to selectively remove the documents listed in Pages “Open Recent” Menu by modifying the pList. (Pages only gives you the option to clear all.)

The applescript is failing to write back “data” type values to the pList…

e.g. Item 0 of CustomListItems of RecentDocuments of the pList “com.apple.iWork.Pages.LSSharedFileList.pList” should contain 3 values:
Bookmark (of type Data)
Icon (of type Data)
Name (of type String)

My applescript only writes the Name value, even though as far as I can tell it contain all the correct data.

Any ideas?

WARNING: Before you run this script, be sure to back up your pList!!

--"edit recent documents" v1 by Alnoor

--Selectively remove listed documents in Pages "Open Recent" Menu
-----------------------

--PROPERTIES:

global prefsFile
(*
global myData
*)

property prefsFolder : (((path to home folder) as text) & "Library:Preferences:") as alias
property prefsName : "com.apple.iWork.Pages.LSSharedFileList"


--HANDLERS:

--VERIFY PLIST
on verifyplist()
	tell application "Finder"
		if not (exists file (prefsName & ".plist") of folder prefsFolder) then
			display dialog "No recent documents for \"Pages\" found!" buttons {"Cancel"} default button 1 with icon 0
		else
			set prefsFile to (file (prefsName & ".plist") of prefsFolder) as alias
		end if
	end tell
end verifyplist

--READ SINGLE KEY
on readsinglekey(myKey)
	tell application "System Events"
		prefsFile as text
		value of property list item myKey of property list file the result
	end tell
end readsinglekey

--WRITE SINGLE KEY
on writesinglekey(myKey, myValue)
	tell application "System Events"
		prefsFile as text
		set (value of property list item myKey of property list file the result) to myValue
	end tell
end writesinglekey


--QUIT PAGES
on quitPages()
	tell application "System Events" to get name of processes
	set application_list to result
	if application_list contains "Pages" is true then
		display dialog "\"Pages\" will quit!" buttons {"Cancel", "Continue"} default button 2 with icon 0
		tell application "Pages" to quit
	end if
end quitPages


--SCRIPT:

--welcome
display dialog "Remove selected documents from \"Open Recent\" Menu?" with icon 1

--initialize
my quitPages()
my verifyplist()
set myData to my readsinglekey("RecentDocuments") --i.e "RecentDocuments" of pList
set myCustomListitems to CustomListItems of myData --i.e "CustomListItems" of pList

--read Names of Recent Docs...
set myNames to {}
repeat with i from 1 to count of myCustomListitems
	set aName to |Name| of item i of myCustomListitems
	set myNames to myNames & aName
end repeat

--choose recent docs to delete
activate me
set mySelection to choose from list myNames with prompt "Delete document(s):" with multiple selections allowed
if mySelection is not false then --i.e user didn't cancel
	
	--make new CustomListitems
	set myCustomListitems_new to {}
	repeat with i from 1 to count of myCustomListitems
		set aName to |Name| of item i of myCustomListitems
		if aName is not in mySelection then
			set myCustomListitems_new to myCustomListitems_new & {item i of myCustomListitems}
		end if
	end repeat
	
	--make new data
	set myData_new to myData
	set CustomListItems of myData_new to myCustomListitems_new
	
	--write to pList
	my writesinglekey("RecentDocuments", myData_new) --*******PROBLEM HERE: ONLY writing "Name" entries of CustomListItems (even though myData_new contains data for "Bookmark" & "Icon")???********
	
end if


--END

AppleScript: 2.3
Browser: Safari 534.57.2
Operating System: Mac OS X (10.6)

Hello.

I have just some hints for you.

The first problem would be that your writeSingleKey handler, does just that, It just writes one item, it doesn’t iterate over the whole list you are passing to it.

I am not totally sure of how you recreate the property list by merely glancing over your code. But general practice is:

To delete a propertylist item, delete the whole item from the property list if it is superfluos. Then save the property-list back to disk. (After Pages has quit! :slight_smile: )

(Look for property list item in the property list suite of the System Events Dictionary.)

I agree. Don’t fiddle with parts of a plist. Just read the entire thing into a variable, and write it back out after modifications:

-- read entire plist into AppleScript record
tell application "System Events"
	set recPlistValue to value of property list file prefsFile-- extension required!
	set myCustomListitems to CustomListItems of RecentDocuments of recPlistValue
end tell

-- modify myCustomListitems as you see fit

-- then modify the record, and write it back out
tell application "System Events"
	set CustomListItems of RecentDocuments of recPlistValue to myCustomListitems
	set value of property list file prefsFile to recPlistValue
end tell

Now you can ditch all those handlers…

That sounds a lot better than what I was going to suggest. But it turns out to have the same problem that dewshi wanted to cure. The plist file ends up containing only the names of the menu items, none of the other data.

The method below works, but dewshi’s checks and warnings need to be added. I’ve split the property list item references into nested ‘tell’ statements to make the plist structure clearer. Named property list items are equivalent to labelled values in an AppleScript record, whereas unnamed property list items are equivalent to items in a list.

set plistPath to (path to preferences from user domain as text) & "com.apple.iWork.Pages.LSSharedFileList.plist"

tell application "System Events"
	tell property list file plistPath
		if (it exists) then
			tell property list item "RecentDocuments"
				tell property list item "CustomListItems"
					-- Get a list of the menu item names and a parallel list of plists for the associated data.
					set {recentNames, RecentPlists} to {value of property list item "Name", text} of every property list item
				end tell
			end tell
		else
			error
		end if
	end tell
end tell

-- Select the names of the items to remove from the menu.
activate
set namesToCut to (choose from list recentNames with prompt "Delete document(s):" with multiple selections allowed)
if (namesToCut is false) then error number -128

tell application "System Events"
	tell property list file plistPath
		tell property list item "RecentDocuments"
			tell property list item "CustomListItems"
				-- Property list items don't understand the 'delete' command, so delete the data for ALL the menu items by setting the value of their container to an empty list.
				set value to {}
				-- Recreate the items to keep from their plist texts.
				repeat with i from 1 to (count recentNames)
					if (item i of recentNames is not in namesToCut) then
						make new property list item at end of property list items with properties {text:item i of RecentPlists}
					end if
				end repeat
			end tell
		end tell
	end tell
end tell

Ah. Of course. Plists are UTF-8, which is not a problem with or values - but cannot be read into a record, they must be read explicitly as .

Maybe I’m missing something, but here alastor933’s code is returning myCustomListitems as a list of records including the Name, Icon and Bookmark for each.

I tried, hard, but not as hard as I maybe should have, but I take your word for that the property list item can’t be deleted with System Events. I live in the belief that that would be done with either Satimage or LateNightSw’s tools. I’m also wondering if it would have worked with System Event’s XML suite (I doubt it).

It does, but it’s not utf-8 encoded text. The items’ values start with"***" when viewed in the Events pane. That made me take a closer look. Plist Editor converts stuff on-the-fly, so I opened the source file in Textwrangler. QED…
System Events happily complies when asked for plist content, but somewhere between the utf-8 source and the destination record it does not convert raw data.
Then, when the script tries to write the garbled item things go wrong, and it disapppears into a digital black hole (/dev/null, I believe).

Edit:

It clicked, just now. AppleScript has string and date classes, but no data class.
But who’s responsible for the conversion between utf-8 source and script’s destination variable?

Perfect!! Thanks Nigel.

This was the bit that was throwing me.
I was trying to figure the way to write back to the pList specifying the Raw Data of Bookmark & Icon as of kind “data”… clearly misguided judging from alastor933’s explanation:

Thanks for all the hints & tips.

Hello.

I tinkered with Nigel’s script a little bit further (with TextEdit as I don’t have Pages) I added a number up front, which I extracted, and used in place of the namesToCut, so that several documents in the recent Items list can have the same name, and you able to choose which one. (Uniqueness.)

This is just a piece, you need to quit TextEdit first and such, hahaha when I have unsaved documents, which I don’t care to save to disk in TextEdit and other apps the same age/standard, I “force quit them from the apple-menu”, the unsaved documents are preserved when the app is opened again, with their contents due to NSDocument functionality, at least in Snow Leopard. WARNING: It may goof if you have too many documents open, so it is recommended only when the contents isn’t really valuable. ”On your own risk!

set plistPath to (path to preferences from user domain as text) & "com.apple.TextEdit.LSSharedFileList.plist"
set recentNames to {}
set namesToCut to {}
tell application "System Events"
	tell property list file plistPath
		if (it exists) then
			tell property list item "RecentDocuments"
				tell property list item "CustomListItems"
					-- Get a list of the menu item names and a parallel list of plists for the associated data.
					set {recentNames, RecentPlists} to {value of property list item "Name", text} of every property list item
				end tell
			end tell
		else
			error
		end if
	end tell
end tell

repeat with i from 1 to (count recentNames)
	set item i of recentNames to (text 2 thru -1 of ("0" & i)) & space & space & item i of recentNames
end repeat

set namesToCut to (choose from list recentNames with prompt "Delete document(s):" with multiple selections allowed)
if (namesToCut is false) then error number -128
# I get the values so only the items are deleted.
set numberlist to {}
repeat with i from 1 to (count namesToCut)
	set end of numberlist to (text 1 thru 2 of item i of namesToCut) as number
end repeat

tell application "System Events"
	tell property list file plistPath
		tell property list item "RecentDocuments"
			tell property list item "CustomListItems" of it
				-- Property list items don't understand the 'delete' command, so delete the data for ALL the menu items by setting the value of their container to an empty list.
				set value to {}
				-- Recreate the items to keep from their plist texts.
				repeat with i from 1 to (count recentNames)
					if i is not in numberlist then
						make new property list item at end of property list items with properties {text:item i of RecentPlists}
					end if
				end repeat
			end tell
		end tell
	end tell
end tell

Ah! That’s good, thanks.

Needs warnings too, in the case that the recent items list is empty or that pList doesn’t exist.
Plus it needs to quit Pages (or TextEdit) before pList is read so it’s up to date.

Hello.

To be totally anal, the situtation is that Pages writes the plist to disk when it quits. So that any changes you make in between gets lost.

Hello.

I wrote a little front end for the script above, as it may come in handy now and then. It grabs all the Recent-items plist files, and lets you choose which one to cleanse. The list with the property list files is not a pretty sight, but should work as expected when assembled with the above.


property sTitle : "Recent Items Forensics"
tell application "System Events"
	set plpth to path to preferences folder from user domain
	set plists to name of every disk item of (plpth as alias) whose name ends with "LSSharedFileList.plist"
	
end tell
set shtnms to {}
set {tids, AppleScript's text item delimiters} to {AppleScript's text item delimiters, "."}
repeat with i from 1 to count plists
	set end of shtnms to (text 2 thru -1 of ("0" & i)) & space & space & text item 3 of item i of plists
end repeat
set AppleScript's text item delimiters to tids
shtnms
set chosenapp to choose from list shtnms with title sTitle with prompt "Choose app to clean up recent items for" default items item 1 of shtnms without multiple selections allowed

if chosenapp is not false then
	set chosenapp to chosenapp as text
	set pfnm to text 1 thru 2 of chosenapp
	set chosenapp to text 5 thru -1 of chosenapp
	
	if running of application chosenapp is true then
		display dialog "You must quit  " & chosenapp & " in order to continue." with title sTitle
		error number -128
	else
		tell application "System Events"
			set daPlist to item pfnm of plists
			-- Here we read in the plist file and everything is as earlier.
			set c to size of disk item daPlist of (plpth as alias)
			if c = 0 then
				display dialog "Nothing to remove ..." with title sTitle
				error number -128
			end if
			set plistfile to (plpth as text) & daPlist
			tell property list file plistfile
				tell property list item "RecentDocuments"
					tell property list item "CustomListItems"
						set c to count its every property list item
					end tell
				end tell
			end tell
			if c = 0 then
				display dialog "Nothing to remove ..." with title sTitle
				error number -128
			end if
                        ” insert code from above here.
			-- here we do what we previously did
		end tell
		
	end if
end if

FYI: {Almost) all relative paths (path to .) are available directly in System Events


tell application "System Events"
	set plists to name of every disk item of preferences folder whose name ends with "LSSharedFileList.plist"
end tell

A timely reminder! Thanks Stefan.

I am not changing it now, as I ponder changing that time consuming filter clause of System Events, into something else.

Along with a final report about how many items where actually deleted, and the opportunity for “re play”/review the contents after changes have been made.

And testing agains the process names of System Events as well as testing for isrunning of the application, since the name might be the process name, if the process name is different from the Application name. I play safe.

And I write it all down here, so I have to do it. :smiley:

Hello

There is a problem in the way you extract the application names.

Here is the piece of code grabbing the names of the preferences files with what is returned on my machine :


tell application "System Events"
	set plpth to path to preferences folder from user domain
	set plists to name of every disk item of (plpth as alias) whose name ends with "LSSharedFileList.plist"
	--> {"com.apple.iWork.Numbers.LSSharedFileList.plist", "com.apple.iWork.Pages.LSSharedFileList.plist", "com.apple.Preview.LSSharedFileList.plist", "com.apple.PropertyListEditor.LSSharedFileList.plist", "com.apple.ScriptEditor2.LSSharedFileList.plist", "com.apple.TextEdit.LSSharedFileList.plist", "com.apple.TextEdit.SandboxedPersistentURLs.LSSharedFileList.plist", "org.clindberg.ManOpen.LSSharedFileList.plist", "org.openoffice.script.LSSharedFileList.plist", "org.videolan.vlc.LSSharedFileList.plist"}
end tell
set shtnms to {}
set {tids, AppleScript's text item delimiters} to {AppleScript's text item delimiters, "."}
repeat with i from 1 to count plists
	set end of shtnms to (text 2 thru -1 of ("0" & i)) & space & space & text item 3 of item i of plists
end repeat
set AppleScript's text item delimiters to tids
shtnms
(*
{"1  iWork", "2  iWork", "3  Preview", "4  PropertyListEditor", "5  ScriptEditor2", "6  TextEdit", "7  TextEdit", "8  ManOpen", "9  script", "10  vlc"}
*)

It seems that this edited one is better


set plpth to path to preferences folder from user domain # I don't like to trigger an OSAX in a tell application block
tell application "System Events"
	set plists to name of every disk item of plpth whose name ends with "LSSharedFileList.plist"
	--> {"com.apple.iWork.Numbers.LSSharedFileList.plist", "com.apple.iWork.Pages.LSSharedFileList.plist", "com.apple.Preview.LSSharedFileList.plist", "com.apple.PropertyListEditor.LSSharedFileList.plist", "com.apple.ScriptEditor2.LSSharedFileList.plist", "com.apple.TextEdit.LSSharedFileList.plist", "com.apple.TextEdit.SandboxedPersistentURLs.LSSharedFileList.plist", "org.clindberg.ManOpen.LSSharedFileList.plist", "org.openoffice.script.LSSharedFileList.plist", "org.videolan.vlc.LSSharedFileList.plist"}
end tell
set shtnms to {}
set {tids, AppleScript's text item delimiters} to {AppleScript's text item delimiters, "."}
repeat with i from 1 to count plists
	# EDITED from here
	item i of plists
	if result starts with "com.apple." then
		text items 3 thru -3 of result
	else
		text items 2 thru -3 of result
	end if
	set end of shtnms to (text 2 thru -1 of ("0" & i)) & space & space & result
	# to here
end repeat
set AppleScript's text item delimiters to tids
shtnms
(*
{"1  iWork.Numbers", "2  iWork.Pages", "3  Preview", "4  PropertyListEditor", "5  ScriptEditor2", "6  TextEdit", "7  TextEdit.SandboxedPersistentURLs", "8  clindberg.ManOpen", "9  openoffice.script", "10  videolan.vlc"}
*)

Yvan KOENIG (VALLAURIS, France) samedi 9 mars 2013 16:24:31

Hello Yvan, and thank you very much for showing the error and the solution.

I think I’ll use your solution for iWorks, and have a look at MsOffice/other things that might need a scheme.

Edit

The standard for specifying bundle-identifers are weak, so I’ll just use some more time on it, taking the last text item before LSSharedFileList.plist (between dots) and use that as an app name, that should work in most cases, if not all.

If Numbers has a process name of iWork.Numbers, please let me know!


set plpth to path to preferences folder from user domain # I don't like to trigger an OSAX in a tell application block
tell application "System Events"
	set plists to name of every disk item of plpth whose name ends with "LSSharedFileList.plist"
end tell
set shtnms to {}
set {tids, AppleScript's text item delimiters} to {AppleScript's text item delimiters, "LSSharedFileList.plist"}
repeat with i from 1 to count plists
	# EDITED from here
	item i of plists
	set appNm to text item 1 of item i of plists
	set AppleScript's text item delimiters to "."
	set appNm to text item -2 of appNm
	set end of shtnms to (text 2 thru -1 of ("0" & i)) & space & space & appNm
	set AppleScript's text item delimiters to "LSSharedFileList.plist"
	#TO HERE
end repeat
set AppleScript's text item delimiters to tids
shtnms
(*
{	"1  Automator", 	"2  Chess", 	"3  Sketch", 	"4  ColorSyncUtility", 	"5  Console", 	"6  Dashcode", 	"7  DashcodeBrowserSimulator", 	"8  grapher","9  IconComposer", "10  InterfaceBuilder3" }

*)

Hello.

Final version: “Recent Items Forensics”, lets you delete items from various Recent Items files.
This is the super version, with Nigels handlers (post #49) that turns utf-16 decomposed text into precomposed text.
The very able Nigel Garvey provided the code that does the work. :slight_smile: This is Nigel’s script, I just provided the “icing”.
You’ll have to quit the app in order to save the changes.

2013.2.10: This is finished until somebody finds a bug!
Thanks to Yvan Koenig for his help in getting things right!

Enjoy!


-- http://macscripter.net/viewtopic.php?pid=161038#p161038
-- ALL Nigel Garvey -- Post #49 
property sTitle : "Recent Items Forensics"
property recentItemIcon : a reference to file ((path to library folder from system domain as text) & "CoreServices:CoreTypes.bundle:Contents:Resources:RecentItemsIcon.icns")

set plpth to (path to preferences folder from user domain)
set pxpth to POSIX path of plpth
set plists to paragraphs of (do shell script "cd " & quoted form of pxpth & "; ls * |sed -e '/lockfile/ d' -ne 's/\\(.*\\)\\(\\.LSSharedFileList.plist\\)/\\1/p'")
set shtnms to {}
set {tids, AppleScript's text item delimiters} to {AppleScript's text item delimiters, "."}
repeat with i from 1 to count plists
	set end of shtnms to (text -2 thru -1 of ("0" & i)) & space & space & (text items -2 thru -1 of item i of plists)
end repeat
set AppleScript's text item delimiters to tids
set chosenapp to choose from list shtnms with title sTitle with prompt "Choose app to clean up recent items for" default items item 1 of shtnms without multiple selections allowed

if chosenapp is not false then
	set chosenapp to chosenapp as text
	set pfnm to text 1 thru 2 of chosenapp
	set chosenapp to text 5 thru -1 of chosenapp
	
	if running of application id (item pfnm of plists) is true then
		display dialog "You must quit " & chosenapp & " in order to continue." with title sTitle buttons {"Ok"} default button 1 with icon recentItemIcon
		error number -128
	end if
	
	tell application "System Events"
		set theDomain to (item pfnm of plists) & ".LSSharedFileList"
		set thePlistFile to theDomain & ".plist"
		-- Here we read in the plist file and everything is as earlier.
		
		set c to size of disk item thePlistFile of (plpth as alias)
	end tell
	if c = 0 then
		display dialog "Nothing to remove ..." with title sTitle buttons {"Ok"} default button 1 with icon recentItemIcon
		error number -128
	end if
	set plistfile to (plpth as text) & thePlistFile
	
	repeat
		
		set namesCut to pruneOpenRecentMenu(theDomain)
		display dialog "I removed " & namesCut & " items(s) from" & chosenapp & "´s Recent items." with title sTitle buttons {"Cancel", "Again"} default button 1 with icon recentItemIcon
		
	end repeat
end if
on pruneOpenRecentMenu(domain)
	-- Get a list of the application's "Open Recent" menu item names. 
	set recentNames to getRecentNames(domain)
	
	-- Ask which items to remove from the menu.
	activate
	try
		set namesToCut to (choose from list recentNames default items item 1 of recentNames with prompt "Delete document(s):" with multiple selections allowed)
	on error
		display dialog "Either the "Open Recent" menu's empty or the input domain's faulty." with title sTitle buttons {"OK"} default button 1 with icon stop
		set namesToCut to false
	end try
	if (namesToCut is false) then error number -128
	
	-- Create individual "delete numbered entry" lines matching the numbers displayed with the selected names.
	set cutRegex to linefeed
	repeat with i from (count namesToCut) to 1 by -1
		set cutRegex to cutRegex & "s/[,[:space:]]+\\{[^\"}]+(\"[^[:cntrl:]]+\\n[^}]*)?\\}//" & word 1 of item i of namesToCut & " ;" & linefeed
	end repeat
	
	-- Derive an edited CustomListItems "array" to use in a "defaults write" shell script.
	set newData to quoted form of text 1 thru -2 of (do shell script ("defaults read " & domain & " RecentDocuments | sed -En '
/\\(/,$ H ;
$ {
   g ;" & ¬
		cutRegex & ¬
		"s/\\\\\\\\/\\\\/g ; #Adjustment to avoid writing back more backslashes than came out!
       s/^[^(]+\\(,?/\\(/ ;
       s/\\);[^)]+$/\\)/p ;
}'") without altering line endings)
	
	-- Write the edited array text back to the plist file.
	do shell script ("defaults write " & domain & " RecentDocuments -dict-add \"CustomListItems\" " & newData)
	return (count namesToCut)
end pruneOpenRecentMenu

on getRecentNames(domain)
	-- Parse the "Open Recent" document names from the plist file.
	set recentNames to (do shell script ("defaults read " & domain & " RecentDocuments |
sed -En '/^[[:space:]]*CustomListItems[[:space:]]*=[[:space:]]*\\(/,/^[[:space:]]+\\)/ s/^[[:space:]]+Name[[:space:]]*=[[:space:]\"]*(.*(\\\\\"|[^\"]))\"?;$/\\1/p' |
sed '= ' |
sed 'N ;
s/\\n/. / ;
s/\\\\\\\\\"/\"/g ;'"))
	-- Convert any Unicode circumlocutions to Unicode characters.
	set recentNames to decodeDefaultsUnicode(recentNames)
	
	return paragraphs of recentNames
end getRecentNames

on decodeDefaultsUnicode(defaultsText)
	set astid to AppleScript's text item delimiters
	set AppleScript's text item delimiters to "\\\\U"
	set output to defaultsText's text items
	repeat with i from 2 to (count output)
		set thisTextItem to item i of output
		set UniChar to (character id hex2Int(text 1 thru 4 of thisTextItem))
		if ((count thisTextItem) > 4) then
			set item i of output to UniChar & text 5 thru -1 of thisTextItem
		else
			set item i of output to UniChar
		end if
	end repeat
	set AppleScript's text item delimiters to ""
	set output to output as text
	set AppleScript's text item delimiters to astid
	
	return output
end decodeDefaultsUnicode

on hex2Int(hexStr)
	set hexDigits to "0123456789abcdef"
	set int to 0
	repeat with thisDigit in hexStr
		set int to int * 16 + (offset of thisDigit in hexDigits) - 1
	end repeat
	
	return int
end hex2Int

iWork’s processes are named:

iBooks Author (yes, two words) its prefs file is : com.apple.iBooksAuthor.LSSharedFileList.plist
Keynote – com.apple.iWork.Keynote.LSSharedFileList.plist
Numbers – com.apple.iWork.Numbers.LSSharedFileList.plist
Pages – com.apple.iWork.Pages.LSSharedFileList.plist

Where is the process name required in the script ?

I ran a subset of your late script and got a wrong behavior :


property sTitle : "Recent Items Forensics"
property recentItemIcon : a reference to file ((path to library folder from system domain as text) & "CoreServices:CoreTypes.bundle:Contents:Resources:RecentItemsIcon.icns")

set plpth to (path to preferences folder from user domain)
set pxpth to POSIX path of plpth
set plists to paragraphs of (do shell script "cd " & quoted form of pxpth & "; ls * |sed -n 's/\\(.*\\)\\(\\.LSSharedFileList.plist\\)/\\1/p'")

(*
com.apple.Console.lockfile
com.apple.Preview
com.apple.Preview.lockfile
com.apple.Preview.SandboxedPersistentURLs.lockfile
com.apple.PropertyListEditor
com.apple.PropertyListEditor.lockfile
com.apple.QuickTimePlayerX.lockfile
com.apple.ScriptEditor2
com.apple.ScriptEditor2.lockfile
com.apple.TextEdit
com.apple.TextEdit.lockfile
com.apple.TextEdit.SandboxedPersistentURLs
com.apple.TextEdit.SandboxedPersistentURLs.lockfile
com.apple.iBooksAuthor
com.apple.iWork.Keynote.lockfile
com.apple.iWork.Numbers
com.apple.iWork.Numbers.lockfile
com.apple.iWork.Pages
com.apple.iWork.Pages.lockfile
com.autodesk.sketchbookpromac.lockfile
com.barebones.textwrangler.lockfile
com.mkanda.OCRTOOLS.lockfile
net.nightproductions.prefSetter.lockfile
org.clindberg.ManOpen
org.libreoffice.script.lockfile
org.openoffice.script
org.videolan.vlc
org.videolan.vlc.lockfile
*)
set shtnms to {}
set {tids, AppleScript's text item delimiters} to {AppleScript's text item delimiters, "."}
repeat with i from 1 to count plists
	set end of shtnms to (text 2 thru -1 of ("0" & i)) & space & space & (text item -1 of item i of plists)
end repeat
shtnms
(*
{"1  lockfile", "2  Preview", "3  lockfile", "4  lockfile", "5  PropertyListEditor", "6  lockfile", "7  lockfile", "8  ScriptEditor2", "9  lockfile", "10  TextEdit", "11  lockfile", "12  SandboxedPersistentURLs", "13  lockfile", "14  iBooksAuthor", "15  lockfile", "16  Numbers", "17  lockfile", "18  Pages", "19  lockfile", "20  lockfile", "21  lockfile", "22  lockfile", "23  lockfile", "24  ManOpen", "25  lockfile", "26  script", "27  vlc", "28  lockfile"} with title "Recent Items Forensics" with prompt "Choose app to clean up recent items for" default items "1  lockfile"
*)

Your code doesn’t grab the correct preferences files.

Yvan KOENIG (VALLAURIS, France) samedi 9 mars 2013 18:19:49

I dropped the “problmatics” and used bundle identifier instead, since I use the Application id and no name, no problem shouldn’t occur, and if they do, then I’m sorry. :wink:

The script is tested and works with Snow Leopard
I see that in Lion or Mountain Lion, many of the items are suffixed with lockfile, you’ll have to devise a scheme to get rid of those, as I won’t try that, as I can’t test it. Feel free…