I usually load a new version for every release to keep my OS fresh while preserving the last version on another partition as backup. I also employ a lot of custom key mappings.
I've figured out how to transfer the majority of my configuration across systems so far but I can't figure out where the custom keyboard shortcut mappings are stored.
Does anybody know where gnome puts these? Are there separate user config (i.e., ~/) and system config (i.e. /etc) files?
5 Answers
Ubuntu has changed since other answers to this question were written.
Keybindings have moved from gconf to dconf. Gconf stores its data in xml files and was accessed by gconf-editor and gconf-tool2. Dconf stores its data in a binary format and is accessed by dconf-editor and gsettings.
The number of places that keybindings are stored is reduced. There is now a centralized dconf path to store window manager keybindings (org.gnome.desktop.wm.keybindings). There are mapping files in the directory /usr/share/gnome-control-center/keybindings/that show how these are applied based on the window manager you are actually using (compiz or metacity).
A second set of non-window-manager related key bindings is stored in the dconf path org.gnome.settings-daemon.plugins.media-keys
There is a third set of keybindings related to power buttons that is stored in the dconf path org.gnome.settings-daemon.plugins.power. There is currently a bug in the GUI that lets you configure keybindings. It doesn't know about these settings. I have a "sleep" button on my keyboard. If I want to reassign it to other functionality, I have to disable the setting in org.gnome.settings-daemon.plugins.power manually. The GUI doesn't do it for me (although it assigns the new functionality just fine).
The other wrinkle is custom key bindings. These are stored in dconf using relocatable schema. Its done this way because there are an arbitrary number of them. A reasonable approach, but it makes listing or modifying them via the command line harder than it should be.
I also found out that the GUI that allows you to assign keybindings is limited in a way that annoys me. The GUI allows exactly ONE keybinding to be assigned to each action. In dconf, you can set an array of bindings for a single action. This is useful to me. For example, I like to have the "close-window" action assigned to the traditonal Alt-F4 as well as to an easier to hit single button on my keybord.
I have written a Perl script to dump all the keybindings to a csv file, or restore them from the csv file. For example to dump the keybindings you might use:
./keybindings.pl -e /tmp/keys.csv
and to restore them you might use:
./keybindings.pl -i /tmp/keys.csv
#!/usr/bin/perl
use strict;
my $action = '';
my $filename = '-';
for my $arg (@ARGV){ if ($arg eq "-e" or $arg eq "--export"){ $action = 'export'; } elsif ($arg eq "-i" or $arg eq "--import"){ $action = 'import'; } elsif ($arg eq "-h" or $arg eq "--help"){ print "Import and export keybindings\n"; print " -e, --export <filename>\n"; print " -i, --import <filename>\n"; print " -h, --help\n"; exit; } elsif ($arg =~ /^\-/){ die "Unknown argument $arg"; } else { $filename = $arg; if (!$action){ if ( -e $filename){ $action='import'; } else { $action='export'; } } }
}
$action='export' if (!$action);
if ($action eq 'export'){ &export();
} else { &import();
}
sub export(){ my $gsettingsFolders = [ ['org.gnome.desktop.wm.keybindings','.'], ['org.gnome.settings-daemon.plugins.power','button'], ['org.gnome.settings-daemon.plugins.media-keys','.'], ]; my $customBindings = [ ]; $filename = ">$filename"; open (my $fh, $filename) || die "Can't open file $filename: $!"; for my $folder (@$gsettingsFolders){ my @keylist = split(/\n/, `gsettings list-recursively $folder->[0]`); foreach my $line (@keylist){ if ($line =~ /^([^ ]+) ([^ ]+)(?: \@[a-z]+)? (.*)/){ my ($path, $name, $value) = ($1,$2,$3); if ($name eq "custom-keybindings"){ $value =~ s/[\[\]\' ]//g; my @c = split(/,/, $value); $customBindings = \@c; } elsif ($name =~ /$folder->[1]/){ if ($value =~ /^\[|\'/){ if ($value =~ /^\[\'(?:disabled)?\'\]$/){ $value = '[]'; } print $fh "$path\t$name\t$value\n"; } } } else { die "Could note parse $line"; } } } for my $folder (@$customBindings){ my $gs = `gsettings list-recursively org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:$folder`; my ($binding) = $gs =~ /org.gnome.settings-daemon.plugins.media-keys.custom-keybinding binding (\'[^\n]+\')/g; my ($command) = $gs =~ /org.gnome.settings-daemon.plugins.media-keys.custom-keybinding command (\'[^\n]+\')/g; my ($name) = $gs =~ /org.gnome.settings-daemon.plugins.media-keys.custom-keybinding name (\'[^\n]+\')/g; $command =~ s/\"/\\\"/g; $command =~ s/^'(.*)'$/$1/g; $command =~ s/\'/\'\\\'\'/g; $command = "\'$command\'"; print $fh "custom\t$name\t$command\t$binding\n" } close($fh);
}
sub import(){ $filename = "<$filename"; open (my $fh, $filename) || die "Can't open file $filename: $!"; my $customcount=0; while (my $line = <$fh>){ chomp $line; if ($line){ my @v = split(/\t/, $line); if (@v[0] eq 'custom'){ my ($custom, $name, $command, $binding) = @v; print "Installing custom keybinding: $name\n"; print `gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom$customcount/ name \"$name\"`; print `gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom$customcount/ command \"$command\"`; print `gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom$customcount/ binding \"$binding\"`; $customcount++; } else { my ($path, $name, $value) = @v; print "Importing $path $name\n"; print `gsettings set \"$path\" \"$name\" \"$value\"`; } } } if ($customcount > 0){ my $customlist = ""; for (my $i=0; $i<$customcount; $i++){ $customlist .= "," if ($customlist); $customlist .= "'/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom$i/'"; } $customlist = "[$customlist]"; print "Importing list of custom keybindings.\n"; print `gsettings set org.gnome.settings-daemon.plugins.media-keys custom-keybindings \"$customlist\"`; } close($fh);
}This includes the fix by user2589537 to allow custom commands with quotes in them.
6How to backup dconf settings like keyboard shortcuts
Dump them all to a file:
dconf dump / > ~/.config/dconf/user.confOpen that file on a text editor and select the settings that you care about:
editor ~/.config/dconf/user.confIf you use Vim, you will want this syntax highlight.
You will soon ask yourself what is
<Primary>.If you don't know the name of the setting, but know how to modify it from a GUI like
unity-control-center, run:dconf watch /and then modify them. The exact setting will then appear on the terminal.
When you want to restore those settings, run:
dconf load / < ~/.config/dconf/user.confGit track the config file to never lose it. Homeshick is my current favorite method.
Tested on Ubuntu 15.10. Tip adapted from here.
Gnome terminal is unfortunately resistant to such edits because of the unpredictable profile IDs.
Related: How can I restore default keyboard shortcuts?
2In 11.10 running Gnome classic I found a set of directories (Custom0, Custom1...) under
$HOME/.gconf/desktop/gnome/keybindingsI copied those directories to the same folder in a clean 12.04 installation (again running with Gnome fallback), logged out and logged in again. The keybindings got a bit messed up in transition (something funny happened to the SUPER modifier) but otherwise they were there.
There is a slight problem with the accepted answer, in that it cannot handle custom commands with quotes in them. I only changed the processing of custom commands to generate correct output.
#!/usr/bin/perl
use strict;
my $action = '';
my $filename = '-';
for my $arg (@ARGV){ if ($arg eq "-e" or $arg eq "--export"){ $action = 'export'; } elsif ($arg eq "-i" or $arg eq "--import"){ $action = 'import'; } elsif ($arg eq "-h" or $arg eq "--help"){ print "Import and export keybindings\n"; print " -e, --export <filename>\n"; print " -i, --import <filename>\n"; print " -h, --help\n"; exit; } elsif ($arg =~ /^\-/){ die "Unknown argument $arg"; } else { $filename = $arg; if (!$action){ if ( -e $filename){ $action='import'; } else { $action='export'; } } }
}
$action='export' if (!$action);
if ($action eq 'export'){ &export();
} else { &import();
}
sub export(){ my $gsettingsFolders = [ ['org.gnome.desktop.wm.keybindings','.'], ['org.gnome.settings-daemon.plugins.power','button'], ['org.gnome.settings-daemon.plugins.media-keys','.'], ]; my $customBindings = [ ]; $filename = ">$filename"; open (my $fh, $filename) || die "Can't open file $filename: $!"; for my $folder (@$gsettingsFolders){ my @keylist = split(/\n/, `gsettings list-recursively $folder->[0]`); foreach my $line (@keylist){ if ($line =~ /^([^ ]+) ([^ ]+)(?: \@[a-z]+)? (.*)/){ my ($path, $name, $value) = ($1,$2,$3); if ($name eq "custom-keybindings"){ $value =~ s/[\[\]\' ]//g; my @c = split(/,/, $value); $customBindings = \@c; } elsif ($name =~ /$folder->[1]/){ if ($value =~ /^\[|\'/){ if ($value =~ /^\[\'(?:disabled)?\'\]$/){ $value = '[]'; } print $fh "$path\t$name\t$value\n"; } } } else { die "Could note parse $line"; } } } for my $folder (@$customBindings){ my $gs = `gsettings list-recursively org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:$folder`; my ($binding) = $gs =~ /org.gnome.settings-daemon.plugins.media-keys.custom-keybinding binding (\'[^\n]+\')/g; my ($command) = $gs =~ /org.gnome.settings-daemon.plugins.media-keys.custom-keybinding command (\'[^\n]+\')/g; my ($name) = $gs =~ /org.gnome.settings-daemon.plugins.media-keys.custom-keybinding name (\'[^\n]+\')/g; $command =~ s/\"/\\\"/g; $command =~ s/^'(.*)'$/$1/g; $command =~ s/\'/\'\\\'\'/g; $command = "\'$command\'"; print $fh "custom\t$name\t$command\t$binding\n" } close($fh);
}
sub import(){ $filename = "<$filename"; open (my $fh, $filename) || die "Can't open file $filename: $!"; my $customcount=0; while (my $line = <$fh>){ chomp $line; if ($line){ my @v = split(/\t/, $line); if (@v[0] eq 'custom'){ my ($custom, $name, $command, $binding) = @v; print "Installing custom keybinding: $name\n"; print `gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom$customcount/ name \"$name\"`; print `gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom$customcount/ command \"$command\"`; print `gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom$customcount/ binding \"$binding\"`; $customcount++; } else { my ($path, $name, $value) = @v; print "Importing $path $name\n"; print `gsettings set \"$path\" \"$name\" \"$value\"`; } } } if ($customcount > 0){ my $customlist = ""; for (my $i=0; $i<$customcount; $i++){ $customlist .= "," if ($customlist); $customlist .= "'/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom$i/'"; } $customlist = "[$customlist]"; print "Importing list of custom keybindings.\n"; print `gsettings set org.gnome.settings-daemon.plugins.media-keys custom-keybindings \"$customlist\"`; } close($fh);
} 2 Save custom keyboard shortcuts
You can save/backup/export custom shortcuts/keybindings using just dconf and sed
Export
dconf dump / | sed -n '/\[org.gnome.settings-daemon.plugins.media-keys/,/^$/p' > custom-shortcuts.conf # ExportThe difference with the usual answer is that this will hold on the file the path to the dconf settings, making easier to import, just dconf load / < file.
Import
dconf load / < custom-shortcuts.conf # ImportNotes
Based on Ciro's answer (also here)
Only for the added custom shortcuts
Note that
dconfonly dumps non-default valuesTo backup you may want to use
custom-shortcuts-$(date -I).confTest if it works by resetting to defaults before the import
gsettings reset-recursively org.gnome.settings-daemon.plugins.media-keys