4

In Gnome's File manager (Nautilus), there's a feature called "Recent Files" which presents itself like a "virtual directory" of sorts, listing the most recently created/modified files in the user's home directory.

I am looking for something equivalent on the CLI. i.e. a virtual folder which can be navigated to, but which presents dynamic results based on the output of say, the find command.

My need arises from the fact that I use emacs for email and one needs to specify a path to each file attachment, hence sending file attachments from different folders is a pain. Life would be nicer if there was a single virtual directory which I knew would have all the recently created/modified files.

If there isn't a ready tool for this, I'd write a script to run the find command searching for the most recent files in the $HOME directory, and create a virtual folder containing symlinks to the files output by find; and run that as a cron or use inotify.

However, it would be lovely if there is already a tool to do this job.

  • 1
    Hi @Vishal Belsare. Are you looking for recent files feature in emacs? Is this what you want? – user88036 Sep 22 '18 at 8:59
  • 1
    Do you want this to also present the recently-used files, as tracked by GNOME? (They are listed in ~/.local/share/recently-used.xbel.) – Stephen Kitt Sep 22 '18 at 10:13
  • @Goro, thanks for this tip. While this will not help me in this situation, because I am looking for recent files from a filesystem perspective, i.e. most recently downloaded files (Firefox), or most recent screenshot of the browser, or the most recently edited document (Libreoffice); but all this while I wasn't aware of recentf ! – Vishal Belsare Sep 22 '18 at 12:23
  • @StephenKitt thanks for pointing this out - I had briefly tried looking up within .local to see where the recent file information is stored - and yes, this information is exactly what I need; albeit I need a 'virtual directory' in which to present those files to emacs. – Vishal Belsare Sep 22 '18 at 12:26
3

This will take the recently-used files referenced in ~/.local/share/recently-used.xbel (or rather, ${XDG_DATA_HOME}/recently-used.xbel), and link them all into a directory called ~/recent:

#!/bin/sh
set -e
mkdir -p ~/recent
rm -f ~/recent/*       # Make sure you don’t have anything you care about here
xmlstarlet sel -t -m '/xbel/bookmark[starts-with(@href, "file://")]' \
    -v 'substring(@href, 8)' -n ${XDG_DATA_HOME:-~/.local/share}/recently-used.xbel |
python -c "import sys, urllib as ul;
sys.stdout.write(ul.unquote(sys.stdin.read().replace('\n', '\0')));" |
xargs -0 ln -st ~/recent

This uses XMLStarlet to extract the file URIs from the list of recently-used documents (ignoring other URIs), feeds them to a Python script which replaces newlines with nul characters and then unquotes the escaped URIs (e.g. + or %20 instead of space), and finally feeds that to xargs which splits all the file names and feeds them to ln (the GNU variant) to create symbolic links.

Note that links will be created regardless of whether the target file still exists; it often happens that the list of recently-used files includes temporary files which have since been deleted.

3

Ideally, the CLI equivalent would do it via gvfs schemes so as to be able to use the recent:/// location as an argument, e.g. as mentioned here

nautilus recent:///

or1

gio open recent:///

would open the recently used files in nautilus just as if you used the Recent button from the sidebar.
That doesn't help much in your case since you need2 a CLI tool that understands gvfs schemes and the only one that I know of is the above mentioned gio. You could run

gio list recent:///

but the output would be useless as you'd get only gio's internal representations of those paths. To see what they correspond to you could use

gio tree recent:///

but that's still almost not usable unless you do some heavy parsing/processing of the output. You could however write your own tool that uses GtkRecentManager to do what you want. To get you started, here is a very basic example in python (no error checking, the target directory must exists and be empty etc):

#!/usr/bin/env python

import gi,sys
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk,Gio
from sys import argv

tg_dir = argv[1]
rec_mgr = Gtk.RecentManager.get_default()
for item in rec_mgr.get_items():
    if item.exists():
        uri = item.get_uri()
        tg = Gio.File.new_for_uri(uri)
        tg_path = tg.get_path()
        b_name = tg.get_basename()
        dt_path = tg_dir + "/" + b_name
        dt = Gio.File.new_for_path(dt_path)
        dt.make_symbolic_link(tg_path, cancellable=None)

If you save this as e.g. my_linker in your PATH and run it with a directory path as an argument

my_linker /path/to/symlinks

it will create symlinks of the most recently used files in that directory.


1: gvfs-open has been deprecated
2: I'm not familiar with emacs - maybe this whole thing could be done via plugins or extensions... I wouldn't know though...

  • My question is not specific to my use of emacs. The need is to access recently created and/or modified and/or accessed files in a single directory. It also is not specific to Gnome Files (Nautilus), because I may have downloaded a PDF through Firefox, which should be accessible in this Recent folder. I quite like your suggestion of GtkRecentManager In fact, useful suggestions in all answers. – Vishal Belsare Sep 24 '18 at 11:16
1

This would probably not work perfectly, but it's a start:

#!/bin/sh

recent_dir=$HOME/recent

mkdir -p "$recent_dir" || exit 1

find "$recent_dir" -type l -ctime +1 -delete

find "$HOME" -type f -mtime -1 -exec sh -c '
    dir=$1; shift
    for pathname do
        link=$dir/${pathname##*/}
        [ -h "$link" ] && continue
        ln -s "$pathname" "$link"
    done' sh "$recent_dir" {} +

This script will create and use a directory called recent in your home directory (make sure that this directory does not already exist, or change the name in the script).

It starts by clearing out symbolic links in the recent directory that are older than a day.

It then finds all regular files (only) in or below your home directory that have been modified in the last 24 hour period, and for each such file it creates a symbolic link in the recent directory.

If two or more files have the same filename, the first found file wins.

The script would also process hidden files and files in hidden directories.

To exclude directories from being searched, use e.g.

find "$HOME" -type d \( -name '.*' -o -name '*-mail' \) -prune \
    -o -type f -mtime -1 -exec sh -c ...as before...

This would exclude hidden directories and any directory whose name ends with -mail.

To have the first find also clean up symbolic links to files that has moved or been deleted, change it into

find "$recent_dir" -type l \( -ctime +1 -o ! -exec test -f {} \; \) -delete
  • thank you. I will try this out : ) As pointed out by another user in a comment to the question, the information presented by Gnome Files' 'Recent Files' is stored in a xml file. Instead of calling find, using the rest of your script, I will try to parse the xml and extract the file paths from there too. But this looks nice to me as it is and more flexible too. – Vishal Belsare Sep 22 '18 at 12:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.