Instantly share code, notes, and snippets.

Embed
What would you like to do?
Detect pipe/file input in Bash / shell script
# How to detect whether input is from keyboard, a file, or another process.
# Useful for writing a script that can read from standard input, or prompt the
# user for input if there is none.
# Source: http://www.linuxquestions.org/questions/linux-software-2/bash-scripting-pipe-input-to-script-vs.-1-570945/
if readlink /proc/$$/fd/0 | grep -q "^pipe:"; then
# Pipe input (echo abc | myscript)
elif file $( readlink /proc/$$/fd/0 ) | grep -q "character special"; then
# Terminal input (keyboard)
else
# File input (myscript < file.txt)
fi
# ALTERNATIVE:
# In Bash you can also use test -t to check for a terminal:
if [ -t 0 ]; then
# Terminal input (keyboard) - interactive
else
# File or pipe input - non-interactive
fi
@AdamDanischewski

This comment has been minimized.

AdamDanischewski commented Mar 27, 2015

Useful tip! I found that if I look for a here string redirected <<< readlink states deleted. I'm not sure if its safe - I've only been playing around with it but it seems to be working so far on my system.
E.g.
if readlink /proc/$$/fd/0 | grep -Eq "^pipe:|deleted"; then
while IFS= read -r PIPED_INPUT || break; do
OPTION_STR="${OPTION_STR} ${PIPED_INPUT} "
done
fi

@kaorihinata

This comment has been minimized.

kaorihinata commented May 12, 2016

If I remember correctly, the traditional way to do this (both POSIXly, and without using Linux specific constructs like /proc) is using the tty command. Additionally, test -t is not Bash specific, and can be found in the POSIX standard these days, though I don't know when it was added originally. Last I checked, even ash supports it.

@gentunian

This comment has been minimized.

gentunian commented Apr 10, 2018

some linux distros does not include file (for instance, alpine linux container) I think it could be more portable this approach:

if readlink /proc/$$/fd/0 | grep -q "^pipe:"; then
    # Pipe input (echo abc | myscript)
elif readlink /proc/$$/fd/0 | grep -q "^/dev"; then
    # Terminal input (keyboard)
else
    # File input (myscript < file.txt)
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment