I play a lot of Java-based games. I find the UX of typing java -jar name-of-game.jar
to be cumbersome, and creating .desktop
files by hand hacky. Are there any automatic .desktop
generators?
2 Answers
Another approach is to tell your system how to execute jar
files directly. You may then have less need to create the desktop files, instead being able just to run the application directly
apt install binfmt-support # Once, as root
chmod u+x name-of-game.jar # Once, for each jar
You can now run the jar
file directly. For example
./name-of-game.jar
Or double-click on the file directly from the file manager.
You may even find that the binfmt-support
package is already installed.
No, but given that .desktop files are 95+% the same, with only a few differences (i.e. variables), it would be very easy to write a simple templating script - using bash + sed, awk, or perl.
In short, it's easy to write your own tools to automate repetitive and tedious tasks.
I'd use perl
for this because perl's a great tool for any text-processing job. This particular templating job is simple enough that you could use bash and sed, but you'd have to be careful about quoting your variables AND about what delimiters you use in the sed
s///
operations - e.g. you can't use /
as the delimiter in a pathname because /
is the pathname separator, you'd have to use :
or =
or some other character that is guaranteed NOT to be in the variable.
Using perl instead of bash + sed avoids all that hassle.
The example below is only a bare minimum example of a templating script. For more complex jobs, I'd be inclined to use one of Perl's excellent templating library modules like Text::Template, but that would be overkill for something as simple as this.
The basic idea is that you create a text file (or a heredoc inside the script, or a variable containing a multi-line string, or an array with each element containing one line of the template, etc) containing a generic version of what you want to generate, with the varying parts of it replaced by some text that will later be replaced by variables.
The replaceable text can be anything you like, but must be something that doesn't occur elsewhere in the template file or in any of the variable data.
I tend to use two underscores and a name followed by another two underscores (e.g. __ICON__
) unless I'm generating program code that might have such strings in it (e.g. as constant or variable names).
You can have whatever fixed/static text you like, and whatever variable/replaceable portions you like.
Then you write a script to replace all of those bits of replaceable text with the values contained in variables.
For example, write a simple script like the one below, call it something like "gen-desktop.pl" and make it executable with chmod +x
:
#!/usr/bin/perl
use strict;
# Very primitive arg handling. Should use Getopt::Std,
# Getopt::Long, or similar. Or read the variables from a CSV
# file or something.
#
# should also do some error checking/data validation. left as
# exercise for the reader :-)
my $exec = shift;
my $name = shift;
my $icon = shift;
# you could read the template from a file instead
# of hard-coding it in the script with a heredoc.
my $template = <<EOF;
[Desktop Entry]
Encoding=UTF-8
Version=1.0
Type=Application
Terminal=false
Exec=__EXEC__
Name=__NAME__
Icon=__ICON__
EOF
# make a copy of the template and modify it
my $output = $template;
$output =~ s/__EXEC__/$exec/g;
$output =~ s/__NAME__/$name/g;
$output =~ s/__ICON__/$icon/g;
print $output;
NOTE: You will want to replace the text inside the $template
variable with a copy of one of your actual desktop files, and edit it to have the appropriate replaceable text. Create variables (and their replaceable text patterns) as you need them.
And run it like:
$ ./gen-desktop.pl "/path/to/executable args" "name of game" "icon for game"
[Desktop Entry]
Encoding=UTF-8
Version=1.0
Type=Application
Terminal=false
Exec=/path/to/executable args
Name=name of game
Icon=icon for game
The script above just prints the modified template to stdout (so you can examine the output and check that it's correct before saving it to a file). You will want to redirect the output to a .desktop file when you run it (e.g. ~/Desktop/game.desktop
).
A better version might take the output filename as another argument, or use "~/Desktop/$n.desktop" and open that file for write and print to it rather than to stdout.
Here's a simpler version, instead of doing multiple regex search and replace operations (s/search/replace/
), it just interpolates the command-line arguments directly into the template heredoc:
#!/usr/bin/perl
print <<__EOF__;
[Desktop Entry]
Encoding=UTF-8
Version=1.0
Type=Application
Terminal=false
Exec=$ARGV[0]
Name=$ARGV[1]
Icon=$ARGV[2]
__EOF__
It produces exactly the same output as the first version. It does the job, but is a lot less flexible.
A bash implementation of this direct interpolation version would be trivial:
#!/bin/bash
cat << EOF
[Desktop Entry]
Encoding=UTF-8
Version=1.0
Type=Application
Terminal=false
Exec=$1
Name=$2
Icon=$3
EOF
If you wanted to batch create lots of .desktop files at once, you could have the script read a CSV or tab-delimited file and generate one .desktop file per input line. Text::CSV is a good module for working with such files (and, despite the name, can work with tab or other characters as the separator too)/
The script would need to loop over each line of the CSV or tab-delimited file, extract the data from it, apply the s///
operations to the template and then print it to the output file.
i.e. the only real difference to the example above is where it gets the variable data from - a file rather than command-line args.
And if you wrote this version of the script to check if each output file existed before opening it for write, it could skip any that did exist...allowing you to just edit the .CSV file, add one or more entries, and run the script -- it would generate only the new .desktop file(s).