I would like a bash script that toggles between: setxkbmap se and setxkbmap us.

Then my intentions are to map that script to CtrlEsc through the Keyboard > custom shortcuts.

The point is that I want to switch keyboard layout with CtrlEscape. How can I implement that?

  • 1
    What DE you use?
    – daisy
    Sep 1, 2012 at 16:03
  • 3
    XKB can set up a key to switch between layouts. This isn't something you'd want to write, but there's probably a pre-cooked configuration for it out there somewhere where you'd only need to select which pair of layouts and which key combination you prefer. Sep 1, 2012 at 23:21

4 Answers 4


I don't know what Desktop Environment you're running, how you gonna assign a shortcut key can varies, but this script works globally, at least on my Ubuntu 12.04 box and Arch Linux:


(setxkbmap -query | grep -q "layout:\s\+us") && setxkbmap se || setxkbmap us
  • Unfortunately, this does not work if you change the layout using a gui method. At least, it doesn't on my xfce box. It only works if you use setxkbmap to switch layouts. The only way I've found that always, consistently works is parsing xmodmap as in my answer below.
    – terdon
    Sep 1, 2012 at 17:40
  • @terdon it works at least on my Ubuntu 12.04 box, have you tried that on your system ?
    – daisy
    Sep 2, 2012 at 1:22
  • Yes, believe me, I have spent a long time dealing with this type of issue. I regularly switch between 3 keyboard layouts (us,fr,es) and between two physical keyboards, one with US layout and one with Spanish. If I use the applet on my tint2 panel to change the keyboard layout, there is no difference at all in the output of setxkbmap. Same goes if I switch layouts using a shortcut set up through the keyboard shortcuts GUI on my LMDE. setxkbmap only changes when I switch using it.
    – terdon
    Sep 2, 2012 at 1:40
  • Really neat with with one line solution. Thanks.
    – Fredrik
    Sep 2, 2012 at 14:27
  • What I ended up doing was saving the line to a .sh file in my home dir. Then mapped ./toggleLayout.sh to ctrl-esc
    – Fredrik
    Sep 2, 2012 at 14:28

the best way would be to not use a script, but to load a two-layer keyboard (eg: setxmodmap "us,se") and redefine the Ctrl-Esc to send ISO_Next_Group

Look at this answer on xkb for how to redefine some keys without need to edit main default files (thus, no need to be root). In the local symbols file (eg: ~/.xkb/symbols/mysymbols) put a small section as:

partial modifier_keys 
xkb_symbols "ctrl_esc_toggle" {
    key <ESC> {
        symbols[Group1]= [ Escape,     ISO_Next_Group ]

the PC_CONTROL_LEVEL2 tells that the sencond symbol for that key is got with Control (instead of Shift).

and in the local keymap file (eg: ~/.xkb/keymap/mykbd; you can create it with setxkbmap "us,se" ; setxkbmap -print > ~/.xkb/keymap/mykbd ) change the xkb_symbols line to add "mysymbols(ctr_esc_toggle)" so you will have someting like:

xkb_symbols   { include "pc+us+se:2+inet(evdev)+terminate(ctrl_alt_bksp)+compose(rwin)+mysymbols(ctr_esc_toggle)"   };

(note the "se:2", the ":2" tells to load the "se" symbols definitions as Group2; you can stack various groups).

you can now load it with: xkbcomp -I$HOME/.xkb ~/.xkb/keymap/mykbd $DISPLAY then Ctrl-Esc will switch between "us" and "se" layouts.

NOTE however that you need to press Ctrl (and hold) before Esc; the other way it doesn't work (it would require defining a virtual modifier for Escape, and I don't know how to do it)

  • 1
    How would leftwin+leftalt+space look like?
    – Hotschke
    Dec 2, 2015 at 17:13
  • @Hotschke, thanks { include "pc+us+ru:2+inet(evdev)+group(win_space_toggle)" }; Jul 8, 2016 at 18:32

There are various answers to similar questions. However, none of them works robustly for me.

The following script should work in all cases. It certainly works on my debian system when switching layouts with setxkbmap:

seven=`xmodmap -pke | grep "keycode  16" | awk '{print \$5}'` 
## If this is the "us" layout
if [ $seven == "ampersand" ]; then
    setxkbmap se
  setxkbmap us

The script parses the output of xmodmap to see if the current layout is "us" or "se". In the "us" layout, SHIFT+7 is mapped to "ampersand". If you will only toggle between the "us" and "se" layouts, having "ampersand" on 7 means you are using the "us" layout and the script will change to "se". If you do not have "ampersand" on 7, the script switches to "us".


If you want to toggle between variants in the same language for example between us lang and us lang with variant intl:


setxkbmap -query | grep -q 'variant:\s\+intl') && setxkbmap -layout us || setxkbmap -layout us -variant intl

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.