Detecting the output stream type of a shell script
See this previous SO question, which covers bash. Tcsh provides the same functionality with filetest -t 1
to see if standard output is a terminal. If it is, then print the color stuff, else leave it out. Here's tcsh:
#!/bin/tcsh
if ( -t 1 ) then
printf "\033[31m Success Color is awesome!\033[0m"
else
printf "Plain Text is awesome!"
endif
detect output stream on linux shell script
When stdout
is not connected to a terminal, it's fully buffered by default. So if you want to be able to detect output immediately (as suggested by the sleep(1);
in the code) you need to flush the buffer after printing.
#include "stdio.h"
void main(){
int i;
for (i=0; i<100; i++){
printf("data: %d\n", i);
fflush(stdout);
sleep(1); // delay 1s
}
}
Then you can pipe the output of the program to something in the script and it will detect the output without waiting for the program to finish.
How can I detect if my shell script is running through a pipe?
In a pure POSIX shell,
if [ -t 1 ] ; then echo terminal; else echo "not a terminal"; fi
returns "terminal", because the output is sent to your terminal, whereas
(if [ -t 1 ] ; then echo terminal; else echo "not a terminal"; fi) | cat
returns "not a terminal", because the output of the parenthetic element is piped to cat
.
The -t
flag is described in man pages as
-t fd True if file descriptor fd is open and refers to a terminal.
... where fd
can be one of the usual file descriptor assignments:
- 0: standard input
- 1: standard output
- 2: standard error
Detect in C if outputting to a terminal
Use isatty()
:
$ man isatty
ISATTY(3) Linux Programmer's Manual ISATTY(3)
NAME
isatty - does this descriptor refer to a terminal
SYNOPSIS
#include <unistd.h>
int isatty(int desc);
DESCRIPTION
returns 1 if desc is an open file descriptor connected to a terminal
and 0 otherwise.
Since stdout
is always file descriptor 1, you can do:
if(isatty(1))
// stdout is a terminal
Checking if output of a command contains a certain string in a shell script
Test the return value of grep:
./somecommand | grep 'string' &> /dev/null
if [ $? == 0 ]; then
echo "matched"
fi
which is done idiomatically like so:
if ./somecommand | grep -q 'string'; then
echo "matched"
fi
and also:
./somecommand | grep -q 'string' && echo 'matched'
how to check for output of a program in bash scripting?
It's possible, but you normally don't.
You can pick the exit code of the last command, 0 is 0 Errors, every other value indicates some kind of error, application specific or just a general error. With $? you get the exit code from the last command, but you have to use it immediately after the command in question.
((3 < 1)) ; err=$?; echo $err
1
((3 > 1)) ; err=$?; echo $err
0
Error messages often depend on LOCALE settings:
erg=$(LC_ALL=C ls nosuchsamplefile 2>&1)
echo "$erg"
ls: cannot access 'nosuchsamplefile': No such file or directory
erg=$(ls nosuchsamplefile 2>&1)
echo $erg
ls: Zugriff auf 'nosuchsamplefile' nicht möglich: Datei oder Verzeichnis nicht gefunden
Comparing words can fail and is inherently insecure. Even by setting the command to a specific setting can't prevent updates from changing the wording and surely, the user had set his Locale to some different value for a reason.
However, 2 > &1 redirects the error stream to the output, which is the default for the screen, but on capturing, it makes a difference. As long as you just script for yourself and in ad hoc situations, approaches can be useful, which don't scale with multiple users and when to be maintained over years.
write to output stream and returning value from shell script function
Would this work?:
#this is a function that returns a value, as well as
#print some messages
function logic(){
echo "start of logic"
echo "perform logic, to get value"
echo "ok" >&2
}
function smain(){
{ local result=$( { { logic ; } 1>&3 ; } 2>&1); } 3>&1
echo "result is >$result<"
if [ "$result" == "ok" ];then
echo "script successful"
else
echo "script failed"
fi
}
smain
Check if user has typed something while script is running
You can use the read command with the timeout option read -t
. For example the below script detects the string 'cc'. You can also specify the number of characters to read with -N
so that user does not have to press enter.
flag=0
while true; do
sleep 3
if [[ $flag -eq 0 ]];then
echo user
else
echo sys
fi
read -t 0.25 -N 2 input
if [[ $input = "cc" ]] ; then
[[ $flag -eq 0 ]] && flag=1 || flag=0
fi
done
Test if a command outputs an empty string
Previously, the question asked how to check whether there are files in a directory. The following code achieves that, but see rsp's answer for a better solution.
Empty output
Commands don’t return values – they output them. You can capture this output by using command substitution; e.g. $(ls -A)
. You can test for a non-empty string in Bash like this:
if [[ $(ls -A) ]]; then
echo "there are files"
else
echo "no files found"
fi
Note that I've used -A
rather than -a
, since it omits the symbolic current (.
) and parent (..
) directory entries.
Note: As pointed out in the comments, command substitution doesn't capture trailing newlines. Therefore, if the command outputs only newlines, the substitution will capture nothing and the test will return false. While very unlikely, this is possible in the above example, since a single newline is a valid filename! More information in this answer.
Exit code
If you want to check that the command completed successfully, you can inspect $?
, which contains the exit code of the last command (zero for success, non-zero for failure). For example:
files=$(ls -A)
if [[ $? != 0 ]]; then
echo "Command failed."
elif [[ $files ]]; then
echo "Files found."
else
echo "No files found."
fi
More info here.
Related Topics
How to Generate a Static HTML File from a Swagger Documentation
When Using Cpan in Linux Ubuntu Should I Run It Using Sudo/As Root or as My Default User
Securing Udp - Openssl or Gnutls or ...
Linux: Checking If a Socket/Pipe Is Broken Without Doing a Read()/Write()
In Linux, Physical Memory Pages Belong to The Kernel Data Segment Are Swappable or Not
How to Get The System Home Directory in Cmake on Linux
Can't Access Publicly Exposed Docker Container Port from External Machine, Only from Localhost
Capture Nethogs Output in Log File
What Is Dma Mapping and Dma Engine in Context of Linux Kernel
How to Store Output from Printf with Formatting in a Variable
How to Search for a Particular String from a .Gz File
Can't Remove, Purge, Unistall Mongodb from Debian
How to Detect If a Server Is Using Spdy
Ubuntu Based Docker-Machine Image