Joey
Joey

Reputation: 164

bash using STDIN in if-statement

Is there a way I can output an error if stdin isn't equal to a particulair file? For example: I want my stdin to be equal to test.txt

./script.sh < test.txt # should run

but

./script.sh < wrong.txt # shouldn't run

Is there a way to do this? Something that looks like this maybe?

if [ STDIN != "test.txt" ]
then 
echo "Error: stdin should be able to test.txt"
fi

Upvotes: 1

Views: 3011

Answers (2)

Petr Skocik
Petr Skocik

Reputation: 60068

On linux, yes, but it isn't portable:

#in a POSIX shell:
if [ "`readlink /dev/fd/0`" != "$PWD/test.txt" ]; then 
    >&2 echo "Error: stdin should be able to test.txt"
fi

This works because on linux, /dev/fd/0 (or /proc/self/fd/0 or /proc/$$/fd/0 (in a shell only)) is a symbolic link that points to the file that represents your stdin.

Upvotes: 4

TrueY
TrueY

Reputation: 7610

You has to check if file handler 0 is redirected to your file or not. You can do something like this:

#!/bin/bash

me=$$
file=$(readlink -n /proc/$me/fd/0)
echo $file   
if [[ "$file" =~ /x.sh$ ]]; then echo YES
else echo NO
fi
# Alternate solution
if [[ "$file" == */x.sh ]]; then echo YES
else echo NO
fi
# Another alternate old style bash solution
# if [ "${file##*/}" = x.sh ]; then

At first it gets the PID of the running . Then if look for the file handler 0 in the virtual /proc filesystem. Every item in /proc/<PID>fd/ is a symlink, which can be read by readlink(1). If it is not redirected the symlink is linked to a dev file like this: /dev/pts/6 if it is redirected to the terminal OR pipe:[33773] if it is a pipe OR socket:[36915] if it is a socket (like /dev/tcp/ibm.com/80) OR /path/filename if a file is redirected. Then the file has to match against a pattern. In my case I tested if the file equals with x.sh.

So the if you type

$ ./x.sh <x.sh; ./x.sh < y.sh

The output is

/home/truey/stackoverflow/x.sh
YES
YES
/home/truey/stackoverflow/y.sh
NO
NO

Upvotes: 3

Related Questions