Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have a Bash script I was trying to make to help me run a rather complex command with small changes that it would ask me about through echo and read.

I have found solutions to force it to run a terminal to execute the command, but I'm not interested in that. What I would like it to do is, if I space out and just hit Enter on it in Nautilus (making it run with Run Software), it'll just gently pop up a notification saying "Please run this from a terminal."

I can get the popup to happen -- as in I know the command -- but I can't get the Bash script to tell if it's being run inside a terminal or not, it seems to always think so. Is it even possible?

share|improve this question

3 Answers 3

From man bash under CONDITIONAL EXPRESSIONS:

-t fd  
    True if file descriptor fd is open and refers to a terminal.

Assuming fd 1 is standard out, if [ -t 1 ]; then should work for you. The Advanced Shell Scripting Guide claims that -t used this way will fail over ssh, and that the test (using stdin, not stdout) should therefore be:

if [[ -t 0 || -p /dev/stdin ]]

-p tests if a file exists and is a named pipe. However, I'd note experientially this is not true for me: -p /dev/stdin fails for both normal terminals and ssh sessions whereas if [ -t 0 ] (or -t 1) works in both cases (see also Gilles comments below about issues in that section of the Advanced Shell Scripting Guide).


If the primary issue is a specialized context from which you wish to call the script to behave in a way appropriate to that context, you can sidestep all these technicalities and save your self some fuss by using a wrapper and a custom variable:

!#/bin/bash

export SPECIAL_CONTEXT=1
/path/to/real/script.sh

Call this live_script.sh or whatever and double click that instead. You could of course accomplish the same thing with command line arguments, but a wrapper would still be needed to make point and click in a GUI file browser work.

share|improve this answer
4  
this is the correct answer - it is also how POSIX says a shell should detect if it is interactive or not. –  mikeserv yesterday
2  
@DanielAmaya - if you redirect input then the script is not being run on a terminal. The question is how to detect if the script is being run on a terminal. –  mikeserv yesterday
2  
Are you sure about the use of || within [ … ] like that? If you use [[ … ]] then it would be fine, but normally the || is used to separate commands, and [ -t 0 is an incorrect invocation of [ because its last ] is missing. There typically isn't a command -p either. I agree with testing for a terminal; that's probably the way to do it. It's just the syntax I'm concerned about. –  Jonathan Leffler yesterday
1  
@JonathanLeffler Right; that should produce a syntax error, since the shell operator || is seen before the required final ] argument to [. –  chepner yesterday
1  
That section from the Advanced Bash-Scripting Guide has several errors. PS1 is not a reliable test to tell whether the shell is interactive. “If a script needs to test whether it is running in an interactive shell” is also confusing: it should be if some code needs to test — a script is usually not running in an interactive shell (but it can be, if it's sourced). Testing for i in $- is the correct way to test if the shell is interactive. Testing -t 0 or -t 2 is the correct way to tell if the script is running in a terminal, which is different from being interactive. –  Gilles yesterday

Test for the existence of the PS1 environment variable:

# If $PS1 is null, not being run from a shell
if [ -z $PS1 ]

Alternatively you can test for it being not null, i.e., run from the shell

if [ -n $PS1 ]
share|improve this answer
4  
this is not reliable. –  mikeserv yesterday
    
There isn't any reliable option here. The three listed are the only 3 I know of, and not a single one of them is reliable. So then, since you seem to know an option that is reliable, why not add your input? Also, the only way that I can consider this being unreliable (especially given the use case), is if the person unsets their PS1 env var. –  Daniel Amaya yesterday
2  
Not true - $PS1 is often exported, and is initialized even when a shell is forced interactive with sh -i. You can always check for a terminal on <&0 with [ -t 0 ]. –  mikeserv yesterday
    
mikeserv@, considering this question is tagged bash, the bash manual simply states: > An interactive shell is one started without non-option arguments and without the -c option whose standard input and error are both connected to terminals (as determined by isatty(3)), or one started with the -i option. PS1 is set and $- includes i if bash is interactive, allowing a shell script or a startup file to test this state. Therefore, every answer in here is 100% reliable. –  Daniel Amaya yesterday
    
Look a little harder at that manual - look under the invocation options - specifically for-i. –  mikeserv yesterday

Another, using the bash options set internal variable, $-.

From .bashrc,

# If not running interactively, don't do anything
case $- in
    *i*) ;;
    *) return;;
esac
share|improve this answer
    
an interactive shell isnt necessarily connected to a terminal. while one started with that connection is automatically started interactive, this also is possible: cmd | sh -i | cmd. –  mikeserv yesterday
    
This code is being executed in a script. It won't be interactive, even if it is running in a terminal. –  Gilles yesterday

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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