1

I am writing a bash script where I pretend to open a new terminal window (in this case a gnome-terminal), execute some commands and change the title of the terminal window.

In order to change the title of the terminal window I am using the function set-title as proposed in this answer. The approach works perfectly when I open manually a new terminal and type inside the terminal set-title MY_TITLE. But in this case, from within a bash script it is not working even if I source the .bashrc file.

#!/bin/bash

gnome-terminal -- /bin/bash -c "echo Hello from terminal 1; set-title Terminal 1; exec /bin/bash";

gnome-terminal -- /bin/bash -c "source ~/.bashrc; echo Hello from terminal 2; set-title Terminal 2; exec /bin/bash";

The two new opened terminals show the same error:

/bin/bash: set-title: command not found

It is obvious that the bash interpreter does not find the function set-title, but I do not know how to force the loading of the .bashrc file when the gnome-terminal is opened.

3
  • 1
    I hadvebeen down the rabbit hole. I ended up using xfce4-terminal. With just, for example: xfce4-terminal --title foo you're good to go. Feb 1 at 14:46
  • 2
    ~/.bashrc usually starts with a line which skips the rest of the file if the shell is not interactive (as with bash -c '...').
    – user414777
    Feb 1 at 15:29
  • With that being said, you don't need any (broken, as in the answer you point to) function in your ~/.bashrc, you can just printf '\033]2;%s\033\\' 'Terminal 1' anywhere you want.
    – user414777
    Feb 1 at 15:36
2

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 ...).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.