(edit: A solution considering named sessions is mentioned at the end of this answer)
I came across this question when I was looking for a particular use-case, but couldn't find any solutions to it, so I'll add mine here:
Upon terminal-launch tmux should:
- check whether there are any unattached sessions and use the first it can find (each session will be attached only once)
- if there are no unattached sessions create a new one
After reading through the tmux man-pages and looking up arrays in bash I was able to come up with the following one-liner:
tmux attach -t ${$(tmux list-sessions -F '#{session_name}' -f '#{==:#{session_attached},0}')[1]} || tmux new
Explanation:
tmux attach -t $A
:
attach to session with content of variable A (in our case the return value of the list-session command + array-index call)
tmux new
:
create new session
together -> tmux attach -t $A || tmux new
:
if tmux attach fails, create a new session
The next part (our $A) is finding an unattached session:
A = ${$B[1]}
: return the second element in the list B (first one seems to always be an empty string)
B = tmux list-sessions -F '#{session_name}' -f '#{==:#{session_attached},0}'
tmux list-sessions
: list all sessions
tmux list-sessions -F '#{session_name}
: -F stands for format and -F '#{session_name}'
tells tmux to only show the name of the session and nothing else when it outputs the list
tmux list-sessions -f '#{==:#{session_attached},0}'
: -f stands for filter and -f '#{==:#{session_attached},0}'
tells tmux to show only those list-elements, where the session_attached
-value is equal to 0
tmux list-sessions -F '#{session_name}' -f '#{==:#{session_attached},0}'
: both flags in combination will output only the session name and only for those elements of the list, where the session_attached
-value is equal to 0 (=unattached sessions)
Example:
My application was for WSL, so I added it to the launch of my Ubuntu profile inside the settings.json of Windows Terminal:
"commandline": "C:\\Windows\\system32\\wsl.exe -d Ubuntu-22.04 tmux attach -t ${$(tmux list-sessions -F '#{session_name}' -f '#{==:#{session_attached},0}')[1]} || tmux new",
Edit:
If you have ([a-zA-Z]) named sessions you can sort the list to put those at the beginning:
tmux attach -t ${$(sort -n <<<"${$(tmux list-sessions -F '#{session_name}' -f '#{==:#{session_attached},0}')[*]}")[1]} || tmux new
If you add tmux new -s "primary" ||
at the beginning of the previous command it will try to create the session with the name "primary" and if it already exists it will only attach to it if it is still unattached, otherwise it will take another unattached session (prioritizing named over unnamed) or just create a new unnamed session if there are no unattached sessions left.
Caveat: each time you run this command and "primary" already exists it will output an error-message that it wasn't able to create a session called "primary" (only visible for a split second)
edit edit:
you can redirect those messages by using &> /dev/null
:
(tmux new -s primary || tmux new -s secondary || tmux new -s tertiary) &> /dev/null || tmux attach -t ${$(sort -n <<<"${$(tmux list-sessions -F '#{session_name}' -f '#{==:#{session_attached},0}')[*]}")[1]} || tmux new"