Tag Archives: see

FreeBSD Desktop – Part 24 – Configuration – Universal File Opener

More then a decade ago when I started to use X11 as a desktop – on Linux then with KDE3 and later with Fluxbox. At first I thought that files are opened by appropriate applications not by their extension as in Windows systems but according to their Magic Numbers. I do not have to tell you how much disappointed I was when I learned the truth πŸ™‚

You may want to check other articles in the FreeBSD Desktop series on the FreeBSD Desktop – Global Page where you will find links to all episodes of the series along with table of contents for each episode’s contents.


Its a short story about cleaning the mess that XDG does and also using custom *.desktop handlers to open the files in the way you want. It know its in the FreeBSD Desktop series but actually it will work on any X11 desktop like Linux or Illumos.

The Table of Contents for the article is right below here.

  • XDG Utils
  • Now You See Me
  • Mime Apps Handlers
  • Generation of Handlers
  • Alternatives

Lets start then.

XDG Utils

After years of using X11 on FreeBSD now with Openbox as my daily driver I used so called xdg-utils package with its *.desktop files. That sometimes driven me nuts. Mess everywhere with doubled ‘the same’ applications listed as possible choices to open a file … almost randomly generated new *.desktop handlers with ‘new’ applications specified to open some files … another dozen of generated *.desktop files from WINE installations … it can only challenge the bullshit and mess of Windows Registry … not sure which one is more messed up (of course its Windows Registry but still).

The xdg-mime(1) is often not useful at all then determining the file type.

$ xdg-mime query filetype FILE.pdf

$ xdg-mime query default application/pdf

If minimalistic mupdf approach is not for you then you can select Atril for example … but you first need to know that is the handler name for the Atril application. You can find that out fast like that.

% find ~/.local/share/applications /usr/local/share/applications | grep atril

We now have the Atril handler name. To set it as new default application for PDF files type the following.

$ xdg-mime default atril.desktop application/pdf

$ xdg-mime query default application/pdf

But this is rather unique moment when XDG works as designed. More often it looks like that.

$ xdg-mime query filetype FILE.doc

$ xdg-mime query filetype FILE.docx

$ xdg-mime query filetype FILE.xls

$ xdg-mime query filetype FILE.xlsx

So when you now ask for application/zip type then what should pop up? LibreOffice for Word/Excel documents or Engrampa for ZIP files?

% xdg-mime query default application/zip                                     

Not very helpful …

Now You See Me

After almost accepting the current ‘tragic’ state of it I came with other idea – to create mine simplified launcher for many of these file types. It started small and is still quite small. The only thing I do now is that I only add new apps for file extensions that are not yet defined.

Its called see.sh and its function is dual:
– to easily replace XDG settings in one place as file opener
– as command line opener for single or multiple files

The construction of see.sh is really simple. It utilizes the idea behind the quote of Antoine de Saint-Exupery which goes like that – “Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.” – its really simple and has nothing to remove from it.

I really appreciate that idea that I now do not have to remember which application is needed (and how its spelled besides the zsh(1) TAB completion) to open any file in command line. Its also faster to type then xdg-open(1) and I am sure that its settings were not modified by some third party app that I just installed because its hardcoded in it.

I also really like see.sh for being very elastic for the environment variables with which the needed application can be started. For example my default DPI for X11 session since more then a decade is 75. That makes fonts little smaller – more information fits on the available screen space. The GTK2/GTK3 applications do not need any tweaks and always look decent or even great but QT5 (and QT4 not so long ago) apps are real bitches when you want to force them to look the way you want (look nice) – especially when run without fully fledged KDE or PLASMA environment. One of such applications is LibreOffice. It looked great when it used GTK framework but after they moved to QT it started to look very ugly with my 75 DPI setting. This is how it looks with its environment unmodified.

Thanks to see.sh I can start LibreOffice with different DPI environment setting then 75 and it looks little better with DPI set to 80. LibreOffice started with QT_FONT_DPI=80 option does not look that bad now – its fonts are not that small and ugly anymore.

Now the text labels on LibreOffice menus are more readable but also not too large.

You may also customize see.sh to first create a backup copy before editing certain files or email them – only your imagination limits you here.

I also wanted its see.sh name to be short and fast to type so with completions its just see[TAB] and then a filename. Of course you may want to rename it to shorter version (or create alias) as see without extension but i like to keep my scripts with extension to distinguish them from native commands – but that is me.

First see.sh detects if one or multiple arguments (files) have been passed to it. If its just a single file then see.sh detects its extension and launches the configured application for it.

If file does not have extension then it checks file’s Magic Number. Currently only detection for plain text files is implemented with file(1) command.

If you pass multiple arguments (files) to see.sh then separate see.sh processes will be launched against each given file in parallel. Recursion generally.

Every time you select new application in graphical mode the new *.desktop file is created as a result with userapp-${APPNAME}-${RANDOM_STRING}.desktop name under ~/.local/share/applications directory. I am not sure that its the tidiest way possible. Often very ugly and strange handler filenames are generated – with spaces or quotation marks. Its really far from UNIX way of doing things and its philosophy.

This is how ~/.local/share/applications directory looked on my machine after some time. Notice the selected file.

After some cleanup and modifications it looks little better.

The XDG keeps its associations in the ~/.config/mimeapps.list file. Have a look how messed it gets after some usage.

After some more cleanup and removal of all unneeded userapp-${APPNAME}-${RANDOM_STRING}.desktop entries it starts to look more organized.

Every time see.sh will find out that it does not have handler for a file it will gracefully remind one to configure it.

Mime Apps Handlers

Many of these *.desktop handlers are not present anymore … but which one? Here is a handy one liner that will either show you the full path of the handler or ‘NOPE’ when one does not exists. This will also tell you if its your ‘custom’ handlers at ~/.local/share/applications or the ‘default’ ones that come with packages and installed software located at /usr/local/share/applications location.

% awk -F'=' '{print $2}' ~/.config/mimeapps.list \
    | tr ';' '\n' \
    | sort -u \
    | sed 1d \
    | while read I
        echo ${I}
        find \
          ~/.local/share/applications \
          /usr/local/share/applications \
            | grep "/${I}" || echo NOPE

Well … maybe not exactly ONE liner but a useful command that will do it πŸ™‚

Here is its output.









If you just want to check which ones are missed then add grep -B 1 NOPE at the end.

% awk -F'=' '{print $2}' ~/.config/mimeapps.list \
    | tr ';' '\n' \
    | sort -u \
    | sed 1d \
    | while read I
        echo ${I}
        find \
          ~/.local/share/applications \
          /usr/local/share/applications \
            | grep "/${I}" || echo NOPE
      done | grep -B 1 NOPE

Here is the (un)expected output.

You can safely remove all missing *.desktop handlers from the ~/.config/mimeapps.list file. You may use sed(1) or graphical editor if that suits you better. The logic behind it is to remove all instances of for example presentations-free18.desktop and then find and replace all instances of doubled semicolons ‘;;‘ into single one ‘;‘.

Generation of Handlers

To generate new *.desktop handlers in orderly fashion you can use mine generate-desktop-handler.sh script. It will create new handler in the ~/.local/share/applications directory and it will make sure you are creating one with an application that actually exists. Here is how it works. I have created new handler for my random-wallpaper-always.sh for setting up random wallpaper from specified directory or to set wallpaper from exact specified file as argument.

% generate-desktop-handler.sh                                       
usage: generate-desktop-handler.sh FILE

% generate-desktop-handler.sh non-existing-executable
NOPE: executable 'non-existing-executable' not found in ${PATH}

% generate-desktop-handler.sh random-wallpaper-always.sh 
INFO: handler '~/.local/share/applications/random-wallpaper-always.sh.desktop' was successfully generated

% cat ~/.local/share/applications/random-wallpaper-always.sh.desktop
[Desktop Entry]
Exec=random-wallpaper-always.sh %f

After you have created new random-wallpaper-always.sh.desktop handler you may want to add it to some image file type like JPG or PNG. In the example below I will add it to JPG file.

First right click on a JPG file with mouse and select Open With and then Other Application….

The select random-wallpaper-always.sh.desktop handler on the list. Make sure to UNCHECK the Remember this application for … files option. If you do not do that it will be the DEFAULT application from now and everytime you would want to open JPG file you will set it as wallpaper πŸ™‚

You may verify that new option is added by right clicking the JPG file and selecting Properties and then go to Open With tab. The random-wallpaper-always.sh.desktop handler will be one of the configured handlers for JPG files – but not the default one.

Now you can see that random-wallpaper-always.sh.desktop handler is available to use when selecting the Open With submenu.

As simple as that – and with tidiness as well.


There are some other alternatives to XDG but I am more then sure that most or all X11 applications support XDG way of doing things while not support the other alternative ones. Thus its far less hustle with just making XDG work as desired by generating needed handlers and using see.sh instead of using them and wasting even more time on the topic – at least that is my current experience.

Feel free to share your thoughts on the topic – maybe you will show me even better approach to this.