79

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?

2
  • 2
    How did you change the settings? Using GConf Editor? I'm guessing you want gconftool-2 --dump /apps/metacity or something like that.
    – Mikel
    Commented Feb 13, 2011 at 6:51
  • 1
    @Mikel Thanks a bunch for that comment. From what I can tell in gconf-editor, most of the keybindings are stored under /apps/metacity while the rest are spread around. I'm currently writing Import/Export python scripts to make backup/restore keybindings a one-click operation. Commented Feb 16, 2011 at 5:09

5 Answers 5

66

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.

8
34

How to backup dconf settings like keyboard shortcuts

  1. Dump them all to a file:

    dconf dump / > ~/.config/dconf/user.conf
    
  2. Open that file on a text editor and select the settings that you care about:

    editor ~/.config/dconf/user.conf
    

    If you use Vim, you will want this syntax highlight.

    You will soon ask yourself what is <Primary>.

  3. 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.

  4. When you want to restore those settings, run:

    dconf load / < ~/.config/dconf/user.conf
    
  5. Git 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?

2
  • 3
    upvoting for dconf watch / - a time saver!
    – benzkji
    Commented May 13, 2020 at 14:58
  • 1
    The only solution that really works, Time saver. Works with Ubuntu 18.04. If you have complex commands in the shortcuts, spaces might be stripped. Just review, and add if necessary.
    – Mijo
    Commented Feb 9, 2021 at 5:16
9

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 # Export

The 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 # Import

Notes

  • Based on Ciro's answer (also here)

  • Only for the added custom shortcuts

  • Note that dconf only dumps non-default values

  • To backup you may want to use custom-shortcuts-$(date -I).conf

  • Test if it works by resetting to defaults before the import

    gsettings reset-recursively org.gnome.settings-daemon.plugins.media-keys
    
3

In 11.10 running Gnome classic I found a set of directories (Custom0, Custom1...) under

$HOME/.gconf/desktop/gnome/keybindings

I 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.

3

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
  • Excellent first answer on AskUbuntu! Congrats!
    – Fabby
    Commented Nov 25, 2014 at 23:18
  • I've integrated your changes into the accepted answer. Commented May 6, 2015 at 19:16

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .