I’ve been using the code from this answer for years, now I’ve found some time to improve it by creating a JSON object per key (the actual output is an array of objects). It is opinionated and it could be improved (I am open to suggestions), however, it works for the schemas, keys and values I have on my system. I have also added the default value of each key (based on this SO answer). It also supports running gsettings
in containers of Flatpak apps (although be warned that it is much slower) and filtering schemas using a search string that is understood by GNU grep
(without any grep
options).
Example objects
[
{
"currentValue": false,
"dataType": "b",
"defaultValue": false,
"key": "symbolic-status-icons",
"schema": "org.blueman.general",
"type": "type"
},
{
"currentValue": 60,
"dataType": "i",
"defaultValue": 60,
"key": "time",
"schema": "org.blueman.plugins.discvmanager",
"type": "type"
},
{
"currentValue": "[{\"adapter\": \"64:79:F0:BE:E9:51\", \"address\": \"C0:DC:DA:14:F7:FB\", \"alias\": \"note10\", \"icon\": \"phone\", \"name\": \"Audio a
nd input profiles\", \"uuid\": \"00000000-0000-0000-0000-000000000000\", \"time\": \"1702752276.9439752\"}]",
"dataType": "aa{ss}",
"defaultValue": "@aa{ss} []",
"key": "recent-connections",
"schema": "org.blueman.plugins.recentconns",
"type": "type"
},
{
"currentValue": 2.3999999999999999,
"dataType": "d",
"defaultValue": 2.3999999999999999,
"key": "display-gamma",
"schema": "org.freedesktop.ColorHelper",
"type": "type"
},
{
"currentValue": -1,
"dataType": "i",
"defaultValue": -1,
"key": "crawling-interval",
"max": 365,
"min": -2,
"schema": "org.freedesktop.Tracker3.Miner.Files",
"type": "range"
},
{
"currentValue": "last",
"defaultValue": "last",
"enumList": [
"last",
"next"
],
"key": "new-tab-position",
"schema": "org.gnome.Terminal.Legacy.Settings",
"type": "enum"
},
{
"currentValue": 0.66000000000000003,
"dataType": "d",
"defaultValue": 0.66000000000000003,
"key": "cross-hairs-opacity",
"max": 1.0,
"min": 0.0,
"schema": "org.gnome.desktop.a11y.magnifier",
"type": "range"
},
{
"currentValue": 500,
"dataType": "u",
"defaultValue": 500,
"key": "delay",
"schema": "org.gnome.desktop.peripherals.keyboard",
"type": "type"
}
]
Function definition
# Dependendies:
# - Bash;
# - GNU `grep`;
# - GNU `sed`;
# - `gsettings`;
# - `jq`;
# - (optional) `flatpak`.
gsls() {
# Variables
# Note: Use `search_string` to limit the schemas. It could be any regex string that GNU grep understands without any option provided.
# Note: Use empty string to search for any schema in a Flatpak app, however, note that running `gsettings` in a Flatpak app (container) takes much longer than doing it directly on the host.
# Note: `app` must be a valid Flatpak app ID.
local search_string="$1"
local app="$2"
local data=''
local cmd key schema
if [ -z "$app" ]; then
cmd='gsettings'
else
if ! command -v flatpak &> /dev/null; then
# shellcheck disable=SC2016 # Expressions don't expand in single quotes, use double quotes for that
echo 'ERROR: `flatpak` cannot be found in `PATH`.'
return
fi
cmd="flatpak run --command=gsettings $app"
fi
# Cycle through matching schemas
for schema in $($cmd list-schemas | grep "$([ -n "$search_string" ] && echo "$search_string" || echo '.*')"); do
# Cycle through all keys of matching schemas
for key in $($cmd list-keys "$schema"); do
local current_value default_value type type_string
type_string="$($cmd range "$schema" $key | tr "\n" " ")"
type="$(grep -Po '^[^ ]+' <<< "$type_string")"
current_value="$($cmd get "$schema" "$key" | sed "s/'/\"/g")"
default_value="$(XDG_CONFIG_HOME=/nonexistent $cmd get "$schema" "$key" | sed "s/'/\"/g")"
# Add those object properties to `data` which are the same for any `type`
data+="{\"schema\": \"$schema\", \"key\": \"$key\", \"type\": \"$type\", "
case "$type" in
'enum')
data+="\"enumList\": [$(sed "s/^enum \(.*\) $/\1/;s/ /, /g;s/'/\"/g" <<< "$type_string")], \"currentValue\": $current_value, \"defaultValue\": $default_value}"
;;
'range')
data+="\"dataType\": \"$(grep -Po "^$type \K[^ ]+" <<< "$type_string")\", \"min\": $(grep -Po "^$type [^ ]+ \K[^ ]+" <<< "$type_string"), \"max\": $(grep -Po "^$type [^ ]+ [^ ]+ \K[^ ]+" <<< "$type_string"), \"currentValue\": $current_value, \"defaultValue\": $default_value}"
;;
'type')
local data_type
data_type="$(grep -Po "^$type \K[^ ]+" <<< "$type_string")"
if grep -q '^@' <<< "$current_value"; then
# shellcheck disable=SC2001 # See if you can use ${variable//search/replace} instead
current_value="$(sed 's/^@[^ ]\+ //' <<< "$current_value")"
# shellcheck disable=SC2001 # See if you can use ${variable//search/replace} instead
default_value="$(sed 's/^@[^ ]\+ //' <<< "$default_value")"
fi
# Add double quotes when the value is not a boolean or a number or an array of a basic type or an optional boolean
if ! grep -q '^[bdhinqstux]$\|^a[a-z]*$\|^mb$' <<< "$data_type"; then
current_value="\"$current_value\""
default_value="\"$default_value\""
# Remove everything up to rightmost space of number types
# Note: This is required because values of some types are prepended by their types (e.g. `uint32 3`).
elif grep -q '^[nqtux]$' <<< "$data_type"; then
current_value="${current_value//* /}"
default_value="${default_value//* /}"
# Replace `nothing` of `mb` (optional boolean) type with `null`
elif grep -q '^mb$' <<< "$data_type" && grep -q '^nothing$' <<< "$current_value"; then
current_value='null'
fi
# Replace `nothing` of `mb` (optional boolean) type with `null`
if grep -q '^mb$' <<< "$data_type" && grep -q '^nothing$' <<< "$default_value"; then
default_value='null'
fi
data+="\"dataType\": \"$data_type\", \"currentValue\": $([ "$data_type" = 'as' ] && echo "$current_value" || sed -z "s/\"/\\\\\"/g;s/\(^\\\\\"\|\\\\\"\n*$\)/\"/g" <<< "$current_value"), \"defaultValue\": $([ "$data_type" = 'as' ] && echo "$default_value" || sed -z "s/\"/\\\\\"/g;s/\(^\\\\\"\|\\\\\"\n*$\)/\"/g" <<< "$default_value")}"
;;
esac
done
done
# Output a JSON string (array of objects)
# Note: The `-S` option sorts the keys alphabetically.
# Note: The `-s` option is required, as `jq` is used to merge individual JSON strings (documents) into an array.
# Note: `sort_by(.key) | sort_by(.schema)` sorts the objects in the array first by `schema`, then by `key`.
jq -Ss 'sort_by(.key) | sort_by(.schema)' <<< "$data"
}
Usage examples
# Get all keys of all schemas
# Note: It takes about 16-18 seconds to complete on my computer (the length of the returned array is 679).
gsls | less
# Get all keys from schemas matching `terminal`
gsls terminal | less
# Get all keys from schemas matching `Prompt` in the Flatpak app `org.gnome.Prompt.Devel` (GNOME Prompt)
# Note: It takes about 11-12 seconds to complete on my computer (the length of the returned array is 49).
gsls Prompt org.gnome.Prompt.Devel | less
List of data types
FYI, here is a list (cheatsheet) of all types that could be used in gsettings
. For more information, see the docs.
(...) = tuple
* = any
? = basic
a = array
b = boolean
d = double
g = signature
h = int32_file_desc
i = int32
m = maybe/nullable/optional
n = int16
o = object_path
q = uint16
r = indefinite_tuple
s = string
t = uint64
u = uint32
v = variant
x = int64
y = byte
{...} = dictionary_entry/object
Possible future improvements
Some stuff to improve:
- use
getopt
;
- convert
dataType
to a more meaningful value (e.g. b
→ boolean
; see the data type list above);
- make the sorting optional;
- optimise the function so that it runs faster (possibly by utilising
gsettings list-recursively
).