I will answer my own question but before explaining the two solutions I have found, I will explain why what I was trying to do did not worked.
Why my initial approach was wrong
If you have custom functions in your ~/.bashrc file, like in my case the one for setting the title of the terminal window, those functions will not be available in a terminal window that is opened from a bash script that executes commands in an automated way (as in the example of my question).
Thanks user414777 for the hint. You were absolute right. My ~/.bashrc file contains the following code at the beginning:
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
By printing the option flags $-
the result is hB (as expected is not an interactive shell), so obviously the set-title
function that I have at the end of the ~/.bashrc, will never be added to the shell.
Solution 1 (Recommended): Using xfce4-terminal
As schrodigerscatcuriosity suggested, this is the easiest solution for the problem. You might not like to install another terminal tool; if (like in my case) you are using Gnome and you use by default gnome-terminal, but the good side is that you can use the xfce4-terminal
for the bash scripts and the gnome-terminal
for your "human" interaction, so besides the titles you also have an extra level of categorization (in case you have many terminal windows opened).
The xfce4-terminal
works a bit different than the gnome-terminal
from within a bash script, but nothing you can not really figure out. In any case you can find below the solution with xfce4-terminal
:
#!/bin/bash
xfce4-terminal --title "Terminal 1" -e "bash -c 'echo Hello from terminal 1; exec /bin/bash'" &
xfce4-terminal --title "Terminal 2" -e "bash -c 'echo Hello from terminal 2; exec /bin/bash'" &
Solution 2: Using xdotool
Another solution that I found to the problem is using xdotool
. xdotool
is a command line tool that can simulate/automate human interaction in the X11 window system.
This solution is overengineering the initial problem since it creates other issues such as the synchronization between the bash script and the X windows system, therefore it is necessary to introduce sleep
commands in the bash script to give time to the X window manager to process the events. This synchronization issues make this solution not reliable since it does not works in 100% of the cases and the sleeping times need to be adapted to the speed of the window system.
Despite I do not recommend to go for this solution for the exposed problem in the question, I decided to introduce the solution in the answer for the shake completeness. Someone else might find it useful to apply this approach for some other purpose:
#!/bin/bash
function set-title(){
sleep 0.2
# local WINDOW_ID=`xdotool getactivewindow`
# local P_ID=`xdotool getactivewindow getwindowpid`
# echo "the window id is: $WINDOW_ID with PID: $P_ID"
xdotool type "set-title $@"
xdotool key KP_Enter
sleep 0.2
}
gnome-terminal -- /bin/bash -c "echo Hello from terminal 1;echo $-; exec /bin/bash";
# xdotool search --onlyvisible --class 'gnome-terminal'
set-title "Terminal 1"
gnome-terminal -- /bin/bash -c "echo Hello from terminal 2; exec /bin/bash";
# xdotool search --onlyvisible --class 'gnome-terminal'
set-title "Terminal 2"
In this case, the function set-title
included in the ~/.bashrc file will work because after the commands have been executed in the gnome-terminal
, the last instruction is /bin/bash
. It loads the shell again and the next commands are forwarded to the terminal using xdotool
, which creates the same events that a human would generate with the input devices (mouse, keyboard, etc ...).
xfce4-terminal
. With just, for example:xfce4-terminal --title foo
you're good to go.~/.bashrc
usually starts with a line which skips the rest of the file if the shell is not interactive (as withbash -c '...'
).~/.bashrc
, you can justprintf '\033]2;%s\033\\' 'Terminal 1'
anywhere you want.