RecentFilesLog - Record recent opened files into Collections

RecentFilesList - Record recent opened files into Collections.

When you double-click on a file or press {Enter} key on selected files,
This script will add the file/files into collections according to its type group.
双击/回车打开文件时,按文件归属的类型组添加到对应文件收集中,即最近打开文件的记录

Although the Windows OS already has a folder "/recent" for recording recent documents,
it is still not enough for me.
I need to record any file every time I double-click, even .exe files

DOpus v13.16.6 (2025.7.2) 增加了文件的添加日期属性,.cct 文件中会记录文件被添加到收集中的日期,文件收集路径下可显示新增的列: "添加日期"
Changes: In file collections a new column, Date Added, is available. This displays the date/time that each item was added to the collection.

Screenshot

Config Options

Collections


Collection

Clear recent collections

To clear all collections, use this command:
要清空最近文件的收集记录,可执行:

dopusrt /col delete "RecentFiles"

(Functions that are currently unachievable, I need help)

To do:
★1.If the file already exists in the collection, update its "added date".
★2.Limit the number of items in a single collection, delete the earliest added files when the collection is full.

v1.0 The first version. 2025.7.30

Usage

Download the .opusscriptinstall file, and double-click it to install.
All done.

You can set a folder format for path coll://RecentFiles like this:(request v13.6.6+)

Download

2025.7.31 : Event.RecentFilesLog-v1.0.opusscriptinstall (5.4 KB)

5 Likes

I think this an interesting approach. I need to experiment with it.

In order to make it more attractive for an English-speaking audience interested in this approach, here is the same code with the Chinese text translated (and some unnecessary stuff eliminated in order to keep it as short as possible).

Disclaimer: I have nothing against Chinese people or the Chinese language as such. But for people like me who have absolutely no clue what to make of Chinese (except for throwing it at Google translate) it is really much easier to get the gist of what is going on when we can read it in plain english.

// RecentFilesLog - Record recent opened files into Collections.
// (c) 2025 bytim

// When you double-click on a file or press {Enter} key on selected files, 
// This script will add the file/files into collections according to its type group.

// Although the Windows OS already has a folder "/recent" for recording recent documents,
// it is still not enough for me.
// I need to record any file every time I double-click, even .exe files

// DOpus v13.16.6 (2025.7.2) 
// Changes: In file collections a new column, Date Added, is available. This displays the date/time that each item was added to the collection.

// To clear all collections, use this command: dopusrt /col delete "RecentFiles"

// To do:
// 1.If the file already exists in the collection, update its "added date".
// 2.Limit the number of items in a single collection, delete the earliest added files when the collection is full.

// v1.0 The first version. 2025.7.30

function OnInit(initData)
{
	initData.name = "Event.RecentFilesLog";
	initData.version = "1.0";
	initData.copyright = "(c) 2025 bytim";
	initData.url = "https://resource.dopus.com/t/recentfileslog-record-recent-opened-files-into-collections/56682";
	initData.desc = DOpus.strings.Get('ScriptDesc');
	initData.default_enable = true;
	initData.min_version = "13.0"; //v13.16.6
	//initData.early_dblclk = true;
	
	//initData.config_desc = DOpus.Create.Map();
	initData.config = DOpus.Create().OrderedMap();
	initData.config_desc = DOpus.Create().OrderedMap();
	initData.config_groups = DOpus.Create().OrderedMap();

	AddConfig('exclude_extensions', ".col.cct.", DOpus.strings.Get('exclude_extensions'), '1. General');
	AddConfig('exclude_paths', DOpus.Create.Vector("/recent", "/temp", "C:\\Windows\\WinSxS", "regex=^ftp://", "regex=^\\\\", "regex=^[A-Za-z]:\\\\TestPath--\\d+"), DOpus.strings.Get('exclude_paths'), '1. General'); //要排除的路径
	AddConfig('limit_number', 2000, DOpus.strings.Get('limit_number'), '1. General');
	AddConfig('separate_type_group', true, DOpus.strings.Get('separate_type_group'), '1. General'); //Whether to create collections by file type group
	AddConfig('use_system_recent_path', false, DOpus.strings.Get('use_system_recent_path'), '1. General'); //C:\Users\<username>\AppData\Roaming\Microsoft\Windows\Recent
	AddConfig('Debug_Level', DOpus.Create.Vector(1, 'debug', 'normal', 'warning', 'off'), DOpus.strings.Get('Debug_Level'), '2. Script Log');

	function AddConfig(name, value, desc, group) {
		initData.config[name] = value;
		initData.config_desc(name) = desc;
		initData.config_groups(name) = group;
	}
}

// Called when a file or folder is double-clicked
function OnDoubleClick(doubleClickData)
{
	var fsu = DOpus.FSUtil;
	if(doubleClickData.is_dir) return; //Ignore folder double click
	var srcPath = doubleClickData.tab.path;
	if(fsu.PathType(srcPath) == "coll") return; //Ignore double-click actions in file collections
	var exclude_paths = Script.config["exclude_paths"];

	for (var n=0; n<exclude_paths.count; n++){
		var pp = "";
		if(exclude_paths(n).search(/^regex=/i) != -1){ //is a regular expression
			pp = exclude_paths(n).replace(/^regex=/i, "");
			Log("Regex patern:" + pp, 1)
			pp = new RegExp(pp, "i");			
			if ((srcPath+"").search(pp) != -1) { return; }
		} else {
			//if(srcPath+"" == fsu.Resolve("/recent")) return; //Ignore /recent dDouble-click operation under the path
			pp = fsu.Resolve(exclude_paths(n));
			Log("exclude_path: " + exclude_paths(n), 1)
			if (fsu.ComparePath(srcPath, pp, "p")) { return; } //Path comparison, if pp is equal to srcPath,or pp is the parent of srcPath, then true
		}
	}

	var excl_exts = "." + Script.config["exclude_extensions"] + "."; //Excluded extensions
	var item = doubleClickData.item;
	var iExt = (item.ext + ".").toLowerCase();
	if (excl_exts.indexOf(iExt) != -1) return; //DO file collection corresponding disk files, .col .cct to be excluded
	//Log(doubleClickData.qualifiers, 1)
	
	cmd = DOpus.Create.Command;
	cmd.ClearFiles;

	var toPath = "/recent";  // or /temp

	if(Script.config["use_system_recent_path"]){
		var lnk = "/recent\\"+doubleClickData.path.filepart+".lnk"
		//var lnk = "/recent\\"+doubleClickData.path.stem+".lnk";
		if(fsu.Exists(lnk))
			cmd.RunCommand('Delete "' + lnk + '"');
		//cmd.RunCommand('Copy FILE="' + doubleClickData.path + '" MAKELINK=softlink TO "' + toPath + '"');
		cmd.RunCommand('Copy FILE="' + doubleClickData.path + '" MAKELINK PATTERN * AS *.lnk TO "' + toPath + '"');		
		//Some programs (such as WPS) will automatically create shortcuts to /recent
	} else { //Add to the corresponding file collection according to the belonging type group
		var collName = DOpus.strings.Get('CollectionName');
		var subCollName = "";

		if(Script.config["separate_type_group"]){
			Log(item.groups.count, 1); //Number of type groups
			//Log(item.groupsobject(0).display_name, 1); //Current type group

			//First determine the custom type group to facilitate obtaining multilingual strings (because the custom group is not set to multilingual)
			//Callable getGroupsNames() Output all groups and find your custom group
			//Also view /dopusdata\Formats\contenttype.off
			if (item.InGroup("name:{7F257B73-5CE8-42E3-9404-9BAD71FC51DB}")) {
				subCollName = DOpus.strings.Get('eBooks');
			} else if(item.groups.count > 0){ //Native type group, automatic conversion of multiple languages
				subCollName = item.groupsobject(0).display_name;
			} else subCollName = DOpus.strings.Get('Others');
			subCollName = '/' + subCollName;
		}
		var now = "";
		//now = DOpus.Create.Date.Format("D#yyyy-MM-dd"); //Append current date "D#yyyy-MM-dd T#HH-mm-ss"
		var fullCollName = collName + subCollName + now;
		
		cmd.AddFile(doubleClickData.path);
		
		//Add to collection, sort by double click time (time added to collection)
		if (cmd.filecount > 0) {
			cmd.RunCommand('Copy COPYTOCOLL=member CREATEFOLDER="coll://' + fullCollName + '" WHENEXISTS=replace'); //Cannot be replaced, only skipped
			//v13.17.1(2025-07-25) New Commands: SetAttr COLLDATEADDED - You can set the "add time" attribute of the files in the collection
			Log("Added to: coll://" + fullCollName, 2);
			var limit_number = Script.config["limit_number"];
			//if (CollFilesCount > limit_number) { //Remove the oldest added one from the collection
				//var oldest = (I don't know how to get the file with the earliest addition date)
				//cmd.RunCommand('Delete REMOVECOLLECTION FILE="coll://' + fullCollName + '/' + oldest + '"'); 
				//There is a problem here: files with the same name but different real paths have the same path in the collection, so there is no guarantee that the current file will be deleted.
			//}
		}
	}
}

//Displays the internal and display names of defined type groups.
function getGroupsNames(){
	for(var g = 0; g<DOpus.filetypegroups.count; g++){
		Log(g +" : "+DOpus.filetypegroups(g)+" : "+DOpus.filetypegroups(g).display_name, 2)
	}
}
function tyof(obj){return DOpus.Typeof(obj);}
function Log(text, level) { //Borrowed from errante
	if(tyof(level) != "int") level = 2;
	if (level === 4 || Script.config['Debug_Level'] < level) {
		if (level == 1) DOpus.Output('<#%vs_dragdrop_normal_action>DEBUG   => ' + text + '</#>');
		else if (level == 2) DOpus.Output(text, false, true); //2=Normal
		else if (level === 3) DOpus.Output('<#%vs_dragdrop_warning_action>WARNING => ' + text + '</#>');
		else DOpus.Output('ERROR   => ' + text, true); //4=Error level, always output
	}
}
1 Like