How can I tell (in ~/.bashrc
) if I'm running in interactive mode, or, say, executing a command over ssh. I want to avoid printing of ANSI escape sequences in .bashrc
if it's the latter.
-
1Choosing whether to print escape sequences or not is better to be based on $TERM value and not on interactiveness of the shell. The variable identifies capabilities of the client terminal which is the part which interprets the escape sequences. – yrk Sep 26 '18 at 16:21
According to man bash
:
PS1 is set and $- includes i if bash is interactive, allowing a shell script or a startup file to test this state.
So you can use:
if [[ $- == *i* ]]
then
do_interactive_stuff
fi
Also:
When an interactive shell that is not a login shell is started, bash reads and executes commands from /etc/bash.bashrc and ~/.bashrc, if these files exist.
So ~/.bashrc
is only sourced for interactive shells. Sometimes, people source it from ~/.bash_profile
or ~/.profile
which is incorrect since it interferes with the expected behavior. If you want to simplify maintenance of code that is common, you should use a separate file to contain the common code and source it independently from both rc files.
It's best if there's no output to stdout from login rc
files such as ~/.bash_profile
or ~/.profile
since it can interfere with the proper operation of rsync
for example.
In any case, it's still a good idea to test for interactivity since incorrect configuration may exist.
-
11Note that $- may contain an i, not necessarily equal it. I use
[[ $- =~ i ]] && echo interactive
– Alex Howansky Feb 27 '13 at 14:47 -
2@AlexHowansky: the asterisks in the equality test make it a test for containing
i
– Dennis Williamson Feb 27 '13 at 18:17 -
1Oh wow didn't even notice those, they look like double quotes on my monitor. It may be time to up the font size. <getting old> – Alex Howansky Feb 28 '13 at 14:29
-
Sometimes, people source it from
~/.bash_profile
or~/.profile
which is incorrect since it interferes with the expected behavior Right. What do you think of sourcing~/.bashrc
from~/.bash_login
? As login shell needn't to to be interactive I guess it's incorrect, too. – Piotr Dobrogost Mar 5 '14 at 20:44 -
2@PiotrDobrogost: This is an excellent discussion of shell startup files. – Dennis Williamson Mar 6 '14 at 2:11
the test
tool can check for this (from the man page):
-t FD True if FD is opened on a terminal.
So you can use for example:
if [ -t 0 ] ; then
echo stdin is a terminal
.....
fi
or
if [ -t 1 ] ; then
echo stdout is a terminal
fi
-
Nice and seems to be portable between shells. TEST it
bash <<< 'test -t 0 && echo Y || echo X'
writesY
,bash -c 'test -t 0 && echo Y || echo X'
writesX
– kyb May 21 '18 at 12:53 -
1this also verifies that the standard input is a TTY; although it can be related but it is NOT the same as the shell's interactive mode, which is requested and indicated by shell's "-i" flag. – yrk Sep 26 '18 at 16:18
Use:
if tty -s; then echo interactive; fi
-
-
this doesn't seem to work for me either, I think this is the correct answer: stackoverflow.com/a/49064632/1223975 – Alexander Mills Mar 2 '18 at 7:58
-
this checks for presence of a TTY on standard input; although it can be related but it is not the same as shell's interactive mode, which is indicated by shell's "-i" flag. – yrk Sep 26 '18 at 16:15
-
I typically look at the output of the program tty.
If you're on a tty, it will tell you which tty you're on. If you're not in interactive mode, it will typically tell you something like "not a tty".
-
4tty -s will set a return value of 0 if you are on a terminal or 1 otherwise without giving you output. You can use it as 'if tty -s; then _interactive; fi' – BillThor May 31 '10 at 1:31
-
1Thanks! It's been a long time since I've needed to do this sort of thing and I guess I forgot some of the details... – chris May 31 '10 at 11:13
This is how red hat does it... Guessing it's the fastest way...
if [ "$-#*i" == "$-" ]; then
It means get the bash parameters, do a substring removal, shortest possible, match everything between the beginning and i. Then check if it's the same as the original bash parameters.
Check you did your job by connecting to the user using sftp, it will fail if non interactive sessions have output