user1934428
user1934428

Reputation: 22291

zsh redirection, together with parameter expansion

I'm writing a shell script S which calls a program P.

P accepts its input from stdin only.

One of the parameters of my script S is optional; if the parameter is present, it denotes a file, which should be fed into P. If the parameter is missing, the stdin of S should be fed into P.

This was my attempt to solve it:

P <${3:-&0}

The idea was: If the (3rd) parameter is a filename, say: foo, it should execute

P <foo

but if it is missing or empty, it should execute

P <&0

which, to my understanding, should be equivalent to simply

P

i.e. read from stdin. This doesn't work, however. While using <&0 literally, works, as in

echo abc|cat <&0

it would produce the error message no such file or directory: &0 when used in the way I'm doing it in my script. This surprises me, since I from the zsh man page, I understand that parameter expansion occurs before setting up the redirection.

Of course I could use the trick

cat $3|P

but this doesn't look very elegant.

Could someone explain to me, why my approach did not work, and what would be a good idiom to use here?

Upvotes: 1

Views: 195

Answers (1)

Parameter expansion happens before redirection, but that doesn't help. <&0 is the <&[NUMBER] operator, whereas <${…} is the < operator followed by the word ${…} which the < operator interprets as a file name. There's no special case that would change the meaning if the file name begins with &.

You can use the exec builtin to set up a redirection and nothing else, so as to avoid duplicating code. This works well when the command is an external command.

( if [[ -n $3 ]]; then exec <$3; fi;
  exec P )

Another approach if you need P to be executed in the outer context (as opposed to a subshell) is to set up the redirection using an intermediate file descriptor.

if [[ -n $3 ]]; then exec 9<$3; else exec 9<&0; fi
P <&9
exec 9<&-

Alternatively, define a function to avoid code duplication.

P () { … }
if [[ -n $3 ]]; then P <$3; else P; fi

Upvotes: 1

Related Questions