259

I like to call :clear-history on panes with a huge scrollback. However, I want to script a way to send this command to all the panes in the various windows.

I know how to send a command to all the windows, courtesy of this question, but how do I send a command to all the panes of which window as well?

send-keys and synchronize-panes from the tmux manpage come to mind, but I'm not sure how to marry them together. But maybe there is a simpler way to do this.

Extra Observations:

Thinking about this a little bit, tmux list-panes -a seems to list all the panes in the current session. Pretty useful to start off with. Where do I go from here?

Community
  • 1
  • 1
Ehtesh Choudhury
  • 7,452
  • 5
  • 42
  • 48
  • For those coming to this question in the hope of finding a solution that applies to each pane, in each window, in each session: https://scripter.co/command-to-every-pane-window-session-in-tmux/ – chb Apr 01 '19 at 16:26

12 Answers12

501

Have you tried following in tmux window with multiple panes

Ctrl-B :

setw synchronize-panes on

clear history
shailesh garg
  • 5,026
  • 1
  • 14
  • 4
  • 75
    Just for the sake of completeness, to turn if off you'd do `Ctrl-b :setw synchronize-panes off` – Mitch Aug 31 '16 at 14:35
  • 27
    and you can bind shortcuts for this on `~/.tmux.conf` by adding: `bind -n C-x setw synchronize-panes on` **and** `bind -n M-x setw synchronize-panes off` – guneysus Oct 30 '16 at 20:00
  • 8
    is possible to set the same shorcut for toggling? – Arnold Roa Jun 12 '17 at 14:31
  • 35
    @ArnoldRoa yes, option will toggle if you leave `on/off`. So `bind -n C-x setw synchronize-panes` – sensation Sep 19 '17 at 10:10
  • 3
    If I add `bind -n C-x setw synchronize-panes` what short cut should I press to invoke ? Is it prefix + C&x. I tried lot of options – Bill Goldberg Aug 28 '18 at 03:53
  • 1
    @BillGoldberg prefix + (CTRL x) – shoujs Sep 28 '18 at 01:06
  • 1
    Do note that while synchronize-panes does synchronise your input, it does NOT synchronise your history, so hitting arrow-up, for example, will bring up whatever was the last thing typed in each of the panes. – Sasha Jun 21 '19 at 18:51
  • @BillGoldberg The shortcut did not work for me either at first. I had to make sure that all tmux sessions were closed and tmux was not running. Otherwise the config was not reloaded – anstue Aug 16 '19 at 10:41
  • Is it possible to synchronise only some panes of a window and not all of them? – Tropilio Apr 10 '20 at 10:15
  • 2
    @anstue You can use "tmux source ~/.tmux.conf" (or wherever you keep your tmux.conf file) while tmux is running. This works the same way as "source ~/.bashrc", and reloads the config while the system is running. This worked for me. – Dave Nov 09 '20 at 13:25
  • What if I wanted to synchronize only a subset of the panes I have? Is it possible? – Abdelhakim AKODADI Apr 14 '22 at 19:30
  • 1
    why is `clear history` needed? – Philip Oct 12 '22 at 10:32
34

A bit late to the party but I didn't want to set and unset synchronize-panes just to send one command so I created a wrapper function around tmux and added a custom function called send-keys-all-panes.

_tmux_send_keys_all_panes_ () {
  for _pane in $(tmux list-panes -F '#P'); do
    tmux send-keys -t ${_pane} "$@"
  done
}

I also create a wrapper around the tmux command to simplify calling this function (for convenience). The wrapper and the above code are all here.

This allows me to run tmux send-keys-all-panes <command> or tmux skap <command to send <command> to all panes.

Note that tmux is aliased to my wrapper function tmux_pp.

kshenoy
  • 1,726
  • 17
  • 31
  • this is bash, but can one do the same from the tmux command prompt, I mean by doing `prefix + :` – Rho Phi Apr 25 '16 at 17:15
  • I don't know how or if that's possible. What's your use-case scenario that you need to send a command via `:`? – kshenoy Apr 30 '16 at 06:40
  • I would recommend calling the bash snippet (`: run "yourscript.sh yourargs..."`); if your command has output your active or specified pane will display the results until you press q, but in this case it shouldn't. Of course you can alias/bind this to your liking. As an aside, inner processes may interpret your keystrokes or their effects differently, so a whitelist or blacklist on `#{pane_current_cmd}` may be necessary. I have ctrl+k bound to send ctrl+l and clear-history; this works fine for shells, but clobbers Vim's buffer. I would need refinement before I could broadcast my ctrl+k. – John P Mar 01 '17 at 04:30
  • This may be more of an X-Y problem; the Tmux command prompt is useful, but it sounds like you're using it because you don't have another command prompt open. You can set up a key binding - without the prefix, if you like - to toggle and focus an extra pane with your shell of choice, instead of sending `:` before each command, losing the output after leaving the command, and all of the pitfalls that come with executing through Tmux. For example, `:run "man cat"` does not result in man appearing in `pidof man` or even `ps auxf | grep man`, nor as 'less', my current pager for man. – John P Mar 01 '17 at 04:44
  • The link is dead – Mateusz Piotrowski Apr 21 '17 at 22:36
  • @MateuszPiotrowski Updated the link – kshenoy Jun 06 '17 at 15:55
  • Dead again, it would be better to just put the content into the answer. – sweenish Jan 18 '22 at 19:47
  • Fixed the link to point to the latest commit so that it's resilient to any future changes. I'm doing all sorts of crap in that file so copy-pasting all of it even if it's just send-keys related will result in a wall of text – kshenoy Feb 09 '22 at 20:13
21

Update June 2019

Quick illustration on how to configure your own binding for synchronize panes.

Added the following into my tmux.conf (the comments certainly apply to my overall configuration):

# synchronize all panes in a window
# don't use control S, too easily confused
# with navigation key sequences in tmux (show sessions)
unbind C-S
bind C-Y set-window-option synchronize-panes

Now, I can toggle the ability to synchronize commands across multiple panes with <C-a><C-y>.

(Yes, I remapped the bind key to Ctrl a).

arcseldon
  • 35,523
  • 17
  • 121
  • 125
  • 1
    This is a very helpful answer. Thank you. – WeakPointer Aug 12 '21 at 22:12
  • 1
    I'm confused, what's the point of `unbind C-S`? – The Guy with The Hat Feb 15 '22 at 06:16
  • I guess it's good form to unbind the key you're about to bind "just in case" - and in this case I think it was simply there because previous examples were binding to ctrl+s. At any rate, it it's optional, but good form. Personally, I use ctrl+s for this key binding. It's completely up to the collective you. – Jim May 18 '22 at 21:45
19

my tmux version is 1.9a, and this works for me, one key is enough for both on and off

bind-key X set-window-option synchronize-panes\; display-message "synchronize-panes is now #{?pane_synchronized,on,off}"
LIU YUE
  • 1,593
  • 11
  • 19
  • 1
    This is the most elegant solution: 1 single keystroke to turn on/off. Works perfect on `tmux 3.0a` – Polymerase Mar 15 '21 at 00:08
  • This message also gives some user feedback when it's changed, invaluable because it's extremely hard to remember that arcane syntax for doing so in `.tmux.conf` (`\; display-message` and `#{?` ) etc. – ijoseph Apr 16 '23 at 18:57
5

None of the above answers worked for me (tmux v2.3), but this did, from the bash command line:

for _pane in $(tmux list-panes -a -F '#{pane_id}'); do 
    tmux clear-history -t ${_pane} 
done 

A more generalized script, for tmux commands other than 'clear-history' would just replace that element with a parameter, eg. $1. Do be careful if you intend to write a script to handle a series of tmux commands, as "-t ${_pane}" will need to be applied to each.

Note that the -a parameter to tmux list-panes is required to cover all panes in all windows in all sessions. Without that, only panes in your current tmux window will be affected. If you have more than one tmux session open and only want to apply the command to panes within the current session, replace -a with -s (It's all in the tmux man page).

I haven't the mod points to comment directly on each of the above answers, so here's why they weren't working for me:

The problem that I had with @shailesh-garg 's answer was that the sync affected only commands issued within the panes, not tmux commands issued using Ctrl-B : which are outside the panes.

The three problems that I had with @kshenoy 's answer were that:

  1. it sends keystrokes to within a pane, not to the tmux operation of that pane, so for instance, if one had a bash shell running in the pane and one used the script to send "clear-history", those would be the keystrokes that would appear in the bash command-line. A work-around would be to send "tmux clear-history" or to pre-pend "tmux " to "$@", but I haven't edited the answer because of my other problems with the answer;
  2. I couldn't figure out how to send a new-line character without literally breaking the line;
  3. Even when I did that, sending "tmux clear-history" had no effect.
ijoseph
  • 6,505
  • 4
  • 26
  • 26
user1404316
  • 463
  • 6
  • 11
3

If you want to send your command to every pane in every window in every session, add this to your .bashrc:

send_command_to_every_pane() {
    for session in `tmux list-sessions -F '#S'`; do
        for window in `tmux list-windows -t $session -F '#P' | sort`; do
            for pane in `tmux list-panes -t $session:$window -F '#P' | sort`; do
                tmux send-keys -t "$session:$window.$pane" "$*" C-m
            done
        done
    done
}

You can then use it like this:

send_command_to_every_pane source ~/.bash_profile

Change "$*" to "$@" if you want that behavior, but in my experience this is what you want.

Daniel Porteous
  • 5,536
  • 3
  • 25
  • 44
2
tmux send-keys -t <session id> <command> C-m  

Replace the "session id" and "command" accordingly.

R J
  • 1,906
  • 1
  • 17
  • 15
  • 1
    would like to say something about this alien language – Muhammad Omer Aslam Feb 03 '18 at 22:04
  • What? English is not hard. But if you have something to say, then say it. – R J Feb 04 '18 at 01:52
  • 5
    **`:D`** dude you need to add some description to your answer as it has very minimal text and for that reason Stackoverflow detects it as a spam or low quality post just add some detail to it so that it does not appear under it. – Muhammad Omer Aslam Feb 04 '18 at 01:57
  • 6
    That's funny, the accepted answer has also no description and only the code, but whatever. – R J Feb 04 '18 at 08:25
1

This is my utility function to do it, only executing the command when there there is nothing running in the pane.

#!/bin/bash

_send_bash_command_to_session() {
    if [[ $# -eq 0 || "$1" = "--help" ]] ; then
        echo 'Usage: _send_bash_command_to_session $session_name what ever command you want: '
        return
    fi
    input_session="$1"
    input_command="${@:2}"
    for _pane in $(tmux list-panes -s -t ${input_session} -F '#{window_index}.#{pane_index}'); do
        # only apply the command in bash or zsh panes.
        _current_command=$(tmux display-message -p -t ${input_session}:${_pane} '#{pane_current_command}')
        if [ ${_current_command} = zsh ] || [ ${_current_command} = bash ] ; then
            tmux send-keys -t ${_pane} "${input_command}" Enter
        fi
    done
}

tmux_set_venv() {
    _current_session=$(tmux display-message -p '#{session_name}')
    _send_bash_command_to_session ${_current_session} workon $1
}

Example targeting a session called dev, enabling a python virtualenv in all panes that are in bash or zsh, avoiding executing the command in panes with vim or any other executable:

_send_bash_command_to_session dev workon myvirtualenv

or easier to remember: to do it in the current session:

tmux_set_venv myvirtualenv

Find my configuration file with this function.

phcerdan
  • 730
  • 7
  • 16
1

You can combine synchronize-panes and send-keys in a single shortcut to send commands to all the panes:

Predefined tmux command clear-history:

bind-key C set-option -w synchronize-panes on\; clear-history \; set-option -w synchronize-panes off

Prompt an arbitrary tmux command:

bind-key p command-prompt -p "Panes command: " "set-option -w synchronize-panes on; %% ; set-option -w -u synchronize-panes"

Prompt an arbitrary shell command:

bind-key p command-prompt -p "Panes command: " "set-option -w synchronize-panes on; send-keys %%\\n ; set-option -w -u synchronize-panes"
duthils
  • 1,181
  • 3
  • 7
1

By default, byobu uses tmux as backend. It's a wrapper that make things much easier:

Shift+F9:
screenshot

Ctrl+F9:
screenshot

Shift+F1

screenshot

Pablo Bianchi
  • 1,824
  • 1
  • 26
  • 30
0

Admittedly only semi-related, I found I could make the status background red when I toggle synchronize-panes so it's obvious when I switch back to a window with an unknown synchronize-panes state:

bind-key C-x setw synchronize-panes on \;  set-window-option status-bg red \; display-message "pane sync on"
bind-key M-x setw synchronize-panes off \;  set-window-option status-bg default \; display-message "pane sync off"
Bruce Edge
  • 1,975
  • 1
  • 23
  • 31
0
# Send the same command to all panes/windows/sessions
bind E command-prompt -p "Command:" \
       "run \"tmux list-panes -a -F '##{session_name}:##{window_index}.##{pane_index}' \
              | xargs -I PANE tmux send-keys -t PANE '%1' Enter\"" 

From @kaushalmodi.

This appears to fully answer OPs question,

… send this command to all the panes in the various windows.

as it works for all panes of all windows, rather than just the currently-active one, like @arcseldon's or @LIU YUE's does.

ijoseph
  • 6,505
  • 4
  • 26
  • 26