public
Last active

Runs the specified command (provided by the first argument) in all tmux panes for every window regardless if applications are running in the terminal or not.

  • Download Gist
execute_in_all_panes.sh
Shell
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
#!/bin/bash
 
# Runs the specified command (provided by the first argument) in all tmux panes
# for every window regardless if applications are running in the terminal or not.
function execute_in_all_panes {
 
# Notate which window/pane we were originally at
ORIG_WINDOW_INDEX=`tmux display-message -p '#I'`
ORIG_PANE_INDEX=`tmux display-message -p '#P'`
 
# Assign the argument to something readable
command=$1
 
# Count how many windows we have
windows=$((`tmux list-windows | wc -l` - 1))
 
# Loop through the windows
for (( window=0; window <= $windows; window++ )); do
tmux select-window -t $window #select the window
 
# Count how many panes there are in the window
panes=$((`tmux list-panes| wc -l` - 1))
# debugging
#echo "window:$window pane:$pane";
#sleep 1
 
# Loop through the panes that are in the window
for (( pane=0; pane <= $panes; pane++ )); do
# Skip the window that the command was ran in, run it in that window last
# since we don't want to suspend the script that we are currently running
# and also we want to end back where we started..
if [ $ORIG_WINDOW_INDEX -eq $window -a $ORIG_PANE_INDEX -eq $pane ]; then
continue
fi
tmux select-pane -t $pane #select the pane
# Send the escape key, in the case we are in a vim like program. This is
# repeated because the send-key command is not waiting for vim to complete
# its action... also sending a sleep 1 command seems to fuck up the loop.
for i in {1..25}; do tmux send-keys C-[; done
# temp suspend any gui thats running
tmux send-keys C-z
# if no gui was running, remove the escape sequence we just sent ^Z
tmux send-keys C-H
# run the command & switch back to the gui if there was any
tmux send-keys "$command && fg 2>/dev/null" C-m
done
done
 
tmux select-window -t $ORIG_WINDOW_INDEX #select the original window
tmux select-pane -t $ORIG_PANE_INDEX #select the original pane
# Send the escape key, in the case we are in a vim like program. This is
# repeated because the send-key command is not waiting for vim to complete
# its action... also sending a sleep 1 command seems to fuck up the loop.
for i in {1..25}; do tmux send-keys C-[; done
# temp suspend any gui thats running
# run the command & switch back to the gui if there was any
tmux send-keys C-c "$command && fg 2>/dev/null" C-m
tmux send-keys "clear" C-m
 
}
 
execute_in_all_panes "echo OH HAI"

Thanks for the script! One suggestion: I would recommend looping over panes and windows using the list-windows/list-panes like such:

  for window in `tmux list-windows -F '#I'`; do 
  for pane in `tmux list-panes -F '#P'`; do

This prevents the script from breaking if the windows were moved to an odd index using move-window. (I commonly move my 0 index window to something else since 0 is far away from my prefix key, backtick (`)).

@yubink: set-option -g base-index 1

if the command fails, I think the fg is never called. "$command; fg 2>/dev/null" may be better

I have this binding in my .tmux.conf to run specified command in all panes/windows/sessions.


bind E command-prompt -p "Command:" \
"run \"tmux list-sessions -F '##{session_name}' | xargs -I SESS \
tmux list-windows -t SESS -F 'SESS:##{window_index}' | xargs -I SESS_WIN \
tmux list-panes -t SESS_WIN -F 'SESS_WIN.##{pane_index}' | xargs -I SESS_WIN_PANE \
tmux send-keys -t SESS_WIN_PANE '%1' Enter\""

Usage:
<tmux PREFIX> E
Enter the command in tmux command prompt: source ~/.alias; clear

@kaushalmodi that seems perfect, thanks!!

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.