1

I want to be able to respawn all panes in my current window that are NOT in tree-mode. I made this script and it works:

for i in $(tmux list-panes -F "#{line} #{pane_id} #{pane_mode} #{pane_active}" | sort -k3 | grep -v tree-mode | awk '{print$2}'); do tmux respawn-pane -k -t $i; done

I want to bind this to tmux-action + R key. But it wont work.

I tried the following:

bind-key R send-keys "for i in $(tmux list-panes -F "#{line} #{pane_id} #{pane_mode} #{pane_active}" | sort -k3 | grep -v tree-mode | awk '{print$2}'); do tmux respawn-pane -k -t $i; done"
bind-key R run-shell "for i in $(tmux list-panes -F "#{line} #{pane_id} #{pane_mode} #{pane_active}" | sort -k3 | grep -v tree-mode | awk '{print$2}'); do tmux respawn-pane -k -t $i; done" Enter

I also tried putting the script into a file and adding the following to .tmux.conf

bind-key R run-shell "./tmux_respawn.sh"

But I get a 127 error an not sure why. If I run the script from my current pane I dont get and error and it works.

I tried building an alias as well in my ~/.bashrc, which works fine from shell, but I get a shell 127 error when trying to run it via a bind key.

alias RespawnTmuxPanes='for i in $(/usr/local/bin/tmux list-panes -F "#{line} #{pane_id} #{pane_mode} #{pane_active}" | sort -k3 | grep -v tree-mode | awk '{print$2}'); do /usr/local/bin/tmux respawn-pane -k -t $i; done'

I really don't want to have a separate file for this script, I want to run it directly from .tmux.conf with a binded key, how can I accomplish this?

2 Answers 2

1

I gave up trying to run the script directly inside of ~/.tmux.conf and built the script as a separate file that I had tmux run.

The script:

#!/bin/bash
for i in $(tmux list-panes -F '#{pane_id} #{pane_mode} #{pane_active}' -f '#{?#{m:tree-mode,#{pane_mode}},0,1}' | sort -k2 | cut -f1 -d' '); do tmux respawn-pane -k -t $i; done

Note: I found a way to use -f with tmux to filter out the tree-mode panes so I did not need to use awk.

Here is the entry in my tmux file:

bind-key R run-shell "/home/mradmin/.tmux_respawn_screens.sh"

This works, as I can now do TMUX-ACTION + R, and it respawns all my panes that are not in tree mode and does the active pane I am in last.

0

This would likely best be done by calling an external script (probably with a fully qualified path, e.g. /home/user/libexec/tmux-foo) as otherwise one must deal with a layered nest of tmux, sh, and awk interpolation and quoting rules. Fun!

Also the command is too complicated, especially given that it is broken in several ways, most notably that the internal " must all be escaped with \", and maybe some of the $variables also need \$variable escaping to protect them from tmux interpolation.

So we need something simple, and a means to reload the tmux configuration to ensure that we get the new configuration, and to confirm that tmux does not yell at us about one of the many typos that you will make (unless you make less typos than I do). Also I already have R for reload so I put the special command on W, which you might want to change around.

bind-key R source-file ~/.tmux.conf \; display-message "source-file done"
bind-key W run-shell "tmux list-panes -F \"#{pane_id} #{pane_mode}\" >> SOMEOUTPUTFROMTMUX"

With this in place we can then run R W and confirm there are no syntax errors tmux reports, and then find the SOMEOUTPUTFROMTMUX file, which may be under your home directory, or otherwise should be fairly easy to find. In another terminal, we can watch this file as we fiddle around with the tmux configuration:

tail -f SOMEOUTPUTFROMTMUX

I've also simplified the tmux command as #{line} was or was not present depending on how I ran the tmux command, and columns that move around make selecting the right column with awk a little difficult. Also grep ... | awk ... can usually be reduced to just a more complicated awk ... expression, which shortens our command and saves some CPU time.

bind-key W run-shell "tmux list-panes -F \"#{pane_id} #{pane_mode}\" | awk '!/tree-mode/{print $1}' >> SOMEOUTPUTFROMTMUX"

Be sure to test with R W often in tmux; trying to do the whole thing at once is complicated. Testing after each new shell command lets you know if you're on the right track or not. The above excludes the tree-mode stuff.

bind-key W run-shell "tmux list-panes -F \"#{pane_id} #{pane_mode}\" | awk '!/tree-mode/{print $1}' | while read id; do echo $id >> SOMEOUTPUTFROMTMUX; done"

Whoops, the output file is empty. tmux apparently does something with the unquoted $id, so we quote it with \$id

bind-key W run-shell "tmux list-panes -F \"#{pane_id} #{pane_mode}\" | awk '!/tree-mode/{print $1}' | while read id; do echo \$id >> SOMEOUTPUTFROMTMUX; done"

but \$id in turn must be quoted to prevent a POSIX shell from doing crazy things with it otherwise, but not single-quoted, because we do need the shell to interpolate it:

bind-key W run-shell "tmux list-panes -F \"#{pane_id} #{pane_mode}\" | awk '!/tree-mode/{print $1}' | while read id; do echo \"\$id\" >> SOMEOUTPUTFROMTMUX; done"

Anyways, following this method it should be possible to add the other tmux variables back in, and then to get the sort command working correctly, and only after the echo results look good replace the caveman debugging (printing output to a file) with the actual tmux command to be run:

... while read id; do tmux respawn-pane -k -t \"\$id\"; done

Or you could do this in an external script, which gives you a file that's a bit easier to test and does not run afoul tmux and sh and awk interpolation and escaping rules.

5
  • Thank you for spending the time to put this post together. Couple problems I am running into. First of all, I agree, didn't need "#{line}" that can be removed (left that in there by accident). But I do need sort -k2 for sorting the active_pane for it to be at the bottom (now -k2 as "#{line}" was removed). If omitted, the list of pane numbers may have the pane I am running it in, in the middle of processing, which will stop the script from running and not complete respawning the other panes, my active pane needs to be the last pane respawned.
    – Dave
    Commented Aug 4, 2022 at 18:58
  • Lastly, I am not seeing the same results when running bind-key R run-shell "tmux list-panes -F \"#{pane_id} #{pane_mode} #{pane_active}\" > SOMEOUTPUTFROMTMUX" in .tmux.conf. It shows the last row of output for the command multiple times for the number of panes I have. If I run the same command in a sperate terminal this does not happen. Expected? With that being said your advice is helpful, maybe I can try getting all escape characters working properly.
    – Dave
    Commented Aug 4, 2022 at 18:58
  • Side note. there is a -f filter parameter that can be used with list-panes. I have no idea how it works as I cant find much documentation on it. Can I use this somehow to avoid using grep/awk?
    – Dave
    Commented Aug 4, 2022 at 18:58
  • > SOMEOUTPUTFROMTMUX is very different from the >> SOMEOUTPUTFROMTMUX I used. I also saw different results from exactly where I ran the tmux commands from (e.g. under run-shell in tmux.conf or in a shell under tmux. This probably makes things trickier.
    – thrig
    Commented Aug 4, 2022 at 19:20
  • Ok. I tried using > SOMEOUTPUTFROMTMUX instead of >> SOMEOUTPUTFROMTMUX Same thing happens. Its just the first entry repeated for as many panes as I have.
    – Dave
    Commented Aug 8, 2022 at 12:57

You must log in to answer this question.

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