the shell will read from the script file or from a device descriptor
Or from a pipe, which is probably the easiest way to get a non-seekable input fd.
Should the shell also read one character at a time from its script input?.
If it wants to support scripts that run commands that read from stdin, and expect to get their input using lines from the script itself.
As in something like this:
$ cat foo.sh
#!/bin/sh
line | sed -e 's/^/* /'
xxx
echo "end."
$ cat foo.sh | bash
* xxx
end.
The line
command reads a single line from standard input (the xxx
) line, and the shell reads the other lines as commands. For this to work, line
also needs to take care not to read the input too far, as otherwise the shell would not see the following lines. With GNU utilities, head -n1
would read too much, as would e.g. sed
. The line
utility from util-linux takes care to read one byte at a time to not read past the newline.
The above script doesn't work with e.g. dash
, as it reads the script full blocks at a time:
$ cat foo.sh | dash
*
dash: 3: xxx: not found
end.
Dash and Busybox read full blocks, the others I tested (Bash, Ksh, mksh
and Zsh) read byte-by-byte.
Note that that's a rather convoluted script, and it doesn't work properly if run as, e.g. bash foo.sh
, since in that case stdin
doesn't point to the script itself, and the xxx
line would be taken as a command. It would probably be better to use a here-doc if ne wants to include data within the script itself. This works with any shell, when run as sh bar.sh
, sh < bar.sh
or cat bar.sh | sh
:
$ cat bar.sh
#!/bin/sh
sed -e 's/^/* /' <<EOF
xxx
EOF
echo "end."
sh < a.sh
, then the stdin of the script would be a file instead. – ilkkachu Jan 08 '19 at 11:16mkfifo p; cat foo.sh > p & bash p
. That seems a bit overly careful: I can't really see there would be a chance for commands in the script to read the same pipe in that case (they can't really get the fd directly, Bash seems to open it at number 255, the script would need to know that). None of the other shells seem to do a byte-by-byte read in that case. – ilkkachu Jan 08 '19 at 12:31