I use kstart
to launch apps via the commandline (such that their process isn’t owned by the terminal and the application doesn’t output there). I want to use fish
to create a “completion” for kstart
, which means I need a way to generate a list of applications which can be launched via kstart
, to pass into the completion command. How can I do this?
I’ve looked at /usr/share/applications/
, but there are many desktop files in there not shown in, for example, the plasma app launcher. I could look at pacman
, but I don’t know how to pull out the runnable applications from my installed packages.
Any suggestions welcome!
Most executables are under /usr/bin.
If you are looking for the executable binary for a certain package/application, you could do for example:
$ pacman -Ql pacman | grep bin
pacman /usr/bin/
pacman /usr/bin/makepkg
pacman /usr/bin/makepkg-template
pacman /usr/bin/pacman
pacman /usr/bin/pacman-conf
pacman /usr/bin/pacman-db-upgrade
pacman /usr/bin/pacman-key
pacman /usr/bin/repo-add
pacman /usr/bin/repo-elephant
pacman /usr/bin/repo-remove
pacman /usr/bin/testpkg
pacman /usr/bin/vercmp
This will show you all the binaries for the package pacman
.
I’m more looking for specifically desktop file applications who are "user"y enough that plasma widgets like the launcher and krunner list them for running:
Is it some attribute within the desktop files that determines them as such? Maybe then I could filter them out with
find
somehow.
OK. I think on KDE Plasma, you can right click on the the icon for the application launcher on your panel. Then chose “Edit Application” or similar wording.
When the application editor windows opens, in the left pane, find the application you are looking for. In the right pane look at the command line it is used in the launcher for starting it and all the other “attributes” related to it.
Ah this is my first time seeing KDE Menu Editor. It doesn’t seem like it can help me generate a list of these applications via commandline though. I imagine the package install via pacman generates these when it sees I have plasma. So I need to see if Plasma has some obscure commandline capability to list these by name. Or else I will just have to curate a list manually myself.
I think I have misunderstood your objective.
Is that you want to generate a full list of all the .dektop files for the packages you have installed with a command line in a terminal?
If that is so, I think it should be feasible in principle but someone with cli-fu or bash-fu needs to get involved here. I’m afraid I am not that person.
Or maybe I am still not getting it. A most probable scenario for me in many cases
If you want an application to continue to run after the terminal is closed you can add the &
at the end of the command like so
thunar /path/to/desired/directory &
the above will open thunar and if I close the terminal thunar will stay open is that what you mean?
I think I may just be confused as to what I’m looking for.
Initially I was using just the commandline bin files for each application, with &
, but certain apps like Anki output a lot to the terminal regardless, and having to get to the end of the command and add &
rather than auto-fill made it a pain. So I wanted to see how KDE launched the apps via the launcher or krunner, and I found kstart
for that.
Knowing .desktop
files in /usr/share/applications/
and ~/.local/share/applications
are what allow for KDE applications, I assumed I could just ls
in those directories to get a list of application names which I can pass into kstart
, but I found there are many hundreds of .desktop
entries in those folders who do not appear as applications in the usual places. So I was hoping there would be some other way to generate such a list of applications which is as pruned as the plasma list.
find /usr/share/applications -iname ‘*kate*.desktop’ /usr/share/applications/org.kde.kate.desktop
kstart –application org.kde.kate
UPD: If you go strictly for user-visible applications, take only .desktop files that contain ‘NoDisplay=false’ or do not contain "NoDisplay’ at all, and contain “Type=Application”.
And please share your completion once you have it; I’m also a fish user and I’ve been too lazy and too busy to actually get into completions.
Can’t you just start app from CLI and append & so the app runs in the background?
This was really helpful, thank you!
If you’ll excuse my ineptitude- I have made a function with a completion!
In my ~/.config/fish/conf.d/custom.fish
file, I have this function called la
:
function la -a 'app'
set file (grep -rli -e "^Name=$app\$" /usr/share/applications/ ~/.local/share/applications/ | path change-extension '' | path basename)
if test -z "$file"
set file (grep -rli -e "^Name=$app" /usr/share/applications/ ~/.local/share/applications/ | path change-extension '' | path basename)
end
kstart --application "$file"
end
It grep
s the applications
folders for the file containing the app name (i.e. Name=Krita
, returns the name of the file, and then uses the fish
path
command to strip the directory part and extension. If the resultant variable is empty, it tests again but expanding the search to allow for incomplete app names (i.e. Name=mpv
rather than Name=mpv Media Player
.
It then passes the resultant file name into kstart
.
In my ~/.config/fish/completions/la.fish
file, I have this complete
command:
complete -f -c la -a '(grep -rl -e "^Type=Application\$" /usr/share/applications/ ~/.local/share/applications/ | xargs -d"\n" grep -rL -e "^NoDisplay=true\$" | xargs -d"\n" pcre2grep -rM -e "\[Desktop Entry\][^\[]*\nName=" | sed -n -e "s/^.*Name=//p")'
This breaks down as follows:
complete -f -c la -a '()'
is a completion for the functionla
, which removes general files from the completion, and instead adds the output of the command substitution in()
.grep -rl -e "^Type=Application\$" /usr/share/applications/ ~/.local/share/applications/
outputs filenames for all files containing the lineType=Application
.xargs -d"\n"
puts those newline-separated filenames into the next function.grep -rL -e "^NoDisplay=true\$"
gets the subset of these files who do not containNoDisplay=true
. These get piped again intoxargs
.pcre2grep -rM -e "\[Desktop Entry\][^\[]*\nName="
outputs the contents of these files from[Desktop Entry]
to the next instance ofName=
(so long as there is not a[
in between, so as to exclude subAction
names).sed -n -e "s/^.*Name=//p"
takes everything from the start of each of these lines to theName=
part, and replaces it with nothing, so as to strip each line down to just the name.
I would LOVE if someone could make this less terrible in any way at all, but for now this works for my purposes. The only concession apart from terrible code seems to be that it can’t run sub actions of the desktop file, such as firefox
’s new-window
and new-private-window
.
I suppose another concession in this solution is the fish
dependance. Without access to the path change-extension
and path basename
commands, something like the bash’s parameter expansion would be needed.
Here’s a bash version. Not sure if this does exactly what you intended though.
Tried to make it easy to understand. It uses fzf
to select the desktop file to run.
#!/bin/bash
Main() {
local search_string="$1" # optional search string (use grep syntax)
local desktop_files=(
/usr/share/applications/*.desktop
~/.local/share/applications/*.desktop
)
local command
command=$(printf "%s\n" "${desktop_files[@]}") # list all .desktop files
command=$(echo "$command" | grep "$search_string") # search for a user string, grep syntax
command=$(echo "$command" | sed 's|.*/||') # strip the path before the name.desktop
command=$(echo "$command" | sort -u) # sort and remove duplicates
command=$(echo "$command" | fzf --reverse) # use fzf to select the command (the desktop file)
[ "$command" ] && xdg-open $command &>/dev/null # run the selected desktop file (if anything was selected)
}
Main "$@"
This looks much nicer, thank you! I imagine its very uncommon for the application name to not be somewhere in the file name for the desktop file. And fzf is a better way to handle multiple matches.
One thing though- on my system, and judging by a web search, quite commonly, xdg-open
can only do the “open” action of an Application
type .desktop file, rather than the execute action. Is that not usually the case on eos? I have found it successfully opens Link
type .desktop files.
Also seems like its possible to do find /usr/share/applications/*.desktop ~/.local/share/applications/*.desktop -printf "%f\n"
in place of the desktop_files
variable, printf
and sed
, unless I’m misunderstanding what was done.
xdg-open should behave the same in EndeavourOS and in most (if not all) linux systems. There might be differences in mime settings which explain something here.
Do you have an example of a Link type .desktop file? I failed to find one on my system…
There’s usually more than one way to do things.
Just use the one you think is best for your case. Of course some ways can be less of a burden to the system than others, or easier understand or write than others. These things may also be important.
When dragging a url or bookmark into dolphin a link desktop file is created where when launched it will open the url in the default browser. Eg:
[Desktop Entry]
Icon=text-html
Name=https://pzplus.tck.mn/db?solved=no&variant=no
Type=Link
URL[$e]=https://pzplus.tck.mn/db?solved=no&variant=no
I imagine the Name field can be changed.
I dragged the URL of this forum thread and dropped it in Thunar, which created a desktop entry like this :
[Desktop Entry]
Version=1.0
Type=Link
Name=Get list of applications via commandline - General system / Applications - EndeavourOS
Comment=
Icon=user-bookmarks
URL=https://forum.endeavouros.com/t/get-list-of-applications-via-commandline/70049/16
I had no problem to use it with xdg-open, it opened in a new tab of my web browser.
Yes- as said-
The behaviour is what I’d expect for Link types, but not for Application types, unfortunately.
My bad, I thought it was the opposite, because I have no problem with .desktop application files. When xdg-open open the .desktop file, the app in the Exec line is launched/executed .