2
0
xdg-desktop-search/xdg-desktop-search
2024-11-03 19:08:55 +01:00

203 lines
5.9 KiB
Bash
Executable File

#!/bin/bash
# Summary: Search for .desktop files with directives that match certain search strings.
# License: MIT <https://opensource.org/license/mit>
# Author: Tilman Kranz <t.kranz@tk-sls.de>
##
# Configuration
name=$(basename "$(readlink -f "$0")")
IFS=":"
xdg_data_dirs=${XDG_DATA_DIRS:-/usr/share/gnome:$HOME/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share:/usr/share}
search_regex=.*
help=false
verbose=false
show_directives_regex=.*
search_directives_regex="(Name|Exec)"
##
# Functions
usage() {
cat << 'EOF'
# XDG-DESKTOP-SEARCH(1) - Search for .desktop files
## SYNOPSIS
```
xdg-desktop-search [ OPTIONS ] SEARCH ...
```
## DESCRIPTION
xdg-desktop-search locates files with names that end in `.desktop` in
sub-directories of name "applications" of a collection of directories
refered to as "XDG data directories". It the searches the lines of such
desktop files for "directives", meaning key-value-assignments such as
`Exec=/some/program` where the assigned value matches one of the search
string given as commandline arguments SEARCH.
xdg-desktop-search prints a list of files that match the given search
criteria, it optionally prints selected directives from the file.
xdg-desktop-search returns successfully if the search rendered one or
more results and unsuccessfully otherwise.
The path of XDG directories searched can be modified by altering the
environment variable `XDG_DATA_DIRS`.
## ARGUMENTS
- `SEARCH`: Search .desktop files with search directives containing this
string. The searched directives are "Name" and "Exec" by default but can be
overridden using the `-s` option (see below).
## OPTIONS
- `-h`, `--help`: Print this message and exit.
- `-v`, `--verbose`: Print directives in found .desktop files.
- `-d STRING`, `--show-directive STRING`: Instead of printing all directives
when searching in verbose mode, print only the directive given by `STRING`
(e.g. "Name"). Option can be repeated to print multiple directives.
- `-s STRING`, `--search-directive STRING`: Instead of searching directives
"Name" and "Exec" for strings containing `SEARCH`, search the given directive
instead (e.g. "Comment"). Option can be repeated to search in multiple directives.
## RETURN VALUES
The command returns 0 if .desktop files were found that match the specified
criteria, 1 on usage error and 2 if no matching .desktop files were found.
## EXAMPLE
Search for the string "firefox" in all .desktop files found in the path
specified by `XDG_DATA_DIRS`. To match, the string "firefox" must be contained
in either the "Exec" or the "Comment" directive. List the matching files, also
show the "Exec" and "TryExec" directives in each found file.
```shell
xdg-desktop-search -s Exec -s Comment -v -d Exec -d TryExec firefox
```
## AUTHOR AND COPYRIGHT
Copyright © 2024 Tilman Kranz <t.kranz@tk-sls.de>
## LICENSE
xdg-desktop-search is distributed under the terms and conditions of the MIT
license <https://opensource.org/license/mit>.
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the “Software”), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
EOF
}
join() {
local IFS="$1"
shift
echo "$*"
}
parse_options() {
local search=()
local search_directives=()
local show_directives=()
local argc=$#
local counter=1
while true ; do
[[ $counter -gt $argc ]] && break
argument=$1
shift
(( counter++ ))
case "$argument" in
-h|--help)
help=true
;;
-v|--verbose)
verbose=true
;;
-d|--show-directive)
[[ $counter -gt $argc ]] && {
echo "ERROR: Missing argument for option -d; aborted." >&2 ;
exit 1 ;
}
show_directives+=( "$1" )
shift
(( counter++ ))
;;
-s|--search-directive)
[[ $counter -gt $argc ]] && {
echo "ERROR: Missing argument for option -s; aborted." >&2 ;
exit 1 ;
}
search_directives+=( "$1" )
shift
(( counter++ ))
;;
*)
search+=( "$argument" )
;;
esac
done
[[ "${#search_directives[@]}" -gt 0 ]] && search_directives_regex="($(join "|" ${search_directives[@]}))"
[[ "${#show_directives[@]}" -gt 0 ]] && show_directives_regex="^($(join "|" ${show_directives[@]}))="
[[ "${#search[@]}" -gt 0 ]] && search_regex="^$search_directives_regex=.*($(join "|" ${search[@]}))"
}
##
# Main Program
parse_options $@
"$help" && { usage ; exit 0 ; }
found=0
for _data_dir in $xdg_data_dirs ; do
data_dir=$(realpath --canonicalize-missing --no-symlinks "$_data_dir")
applications="$data_dir/applications"
[[ -d $applications ]] && for desktop in "$applications"/*.desktop ; do
grep -Eiq "$search_regex" "$desktop" && {
(( found++ ))
if "$verbose" ; then
echo "# $desktop"
grep -Ei "$show_directives_regex" "$desktop"
else
echo "$desktop"
fi
}
done
done
if [[ $found -gt 0 ]] ; then
exit 0
else
exit 2
fi
# vim: tabstop=2 shiftwidth=2 softtabstop=2 expandtab: