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.

TL;DR

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
application/pdf

$ xdg-mime query default application/pdf
mupdf.sh.desktop

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
/usr/local/share/applications/atril.desktop

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
atril.desktop

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

$ xdg-mime query filetype FILE.doc
application/octet-stream

$ xdg-mime query filetype FILE.docx
application/zip

$ xdg-mime query filetype FILE.xls
application/octet-stream

$ xdg-mime query filetype FILE.xlsx
application/zip

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                                     
engrampa.desktop

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
      do
        echo ${I}
        find \
          ~/.local/share/applications \
          /usr/local/share/applications \
            | grep "/${I}" || echo NOPE
        echo
      done

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

Here is its output.

(...)

mupdf.sh.desktop
/home/vermaden/.local/share/applications/mupdf.sh.desktop

planmaker-free18.desktop
NOPE

presentations-free18.desktop
NOPE

see.sh.desktop
/home/vermaden/.local/share/applications/see.sh.desktop

sumatra.sh.desktop
/home/vermaden/.local/share/applications/sumatra.sh.desktop

textmaker-free18.desktop
NOPE

(...)

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
      do
        echo ${I}
        find \
          ~/.local/share/applications \
          /usr/local/share/applications \
            | grep "/${I}" || echo NOPE
        echo 
      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]
Encoding=UTF-8
Version=1.0
Type=Application
NoDisplay=true
Exec=random-wallpaper-always.sh %f
Name=random-wallpaper-always.sh
Comment=random-wallpaper-always.sh

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.

Alternatives

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.

EOF

7 thoughts on “FreeBSD Desktop – Part 24 – Configuration – Universal File Opener

  1. chanio

    Thank you for this great article. Crystal clear and unforgettable. I would recommend it!
    I have tried all the examples. But here at Linux Mint Mate we use /usr/share/applications instead.
    All ok! (BTW: I love your avatar πŸ™‚ )

    Like

    Reply
  2. Fck unx

    Hack on top of a hack on top of a hack, held together with ductape. This is true for unix and every unix like OS.
    It is disgusting, what happened with the CS scene, and sad nix advocados even thinks this is ok.

    I blame programmers and managers for this retardation. All programmers should be fined, open source devs included. Managers should be jailed.
    You guys killed innovation with BS, bloat, convoluted unsafe C code and the list goes on and on and on.
    Fk you all.

    Liked by 1 person

    Reply
  3. Piotr

    Hi,
    I see quite different result on Linux :
    $ xdg-mime query filetype Investigations_STRIPS/Actions/action.docx
    application/vnd.openxmlformats-officedocument.wordprocessingml.document
    so I suppose I can keep using xdg πŸ™‚

    Like

    Reply
    1. vermaden Post author

      Just tried again and it seems to work …

      % xdg-mime query filetype FILE.docx
      application/vnd.openxmlformats-officedocument.wordprocessingml.document

      Strange …

      Like

      Reply
  4. Pingback: Valuable News – 2021/04/26 | πšŸπšŽπš›πš–πšŠπšπšŽπš—

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s