Script doesn't work when I want to use standard input when there are no arguments (files) passed. Is there any way how to use stdin instead of a file in this code?
I tried this:
if [ ! -n $1 ] # check if argument exists
then
$1=$(</dev/stdin) # if not use stdin as an argument
fi
var="$1"
while read line
do
... # find the longest line
done <"$var"
Just substitute bash's specially interpreted
/dev/stdin
as the filename:(Note that bash will actually use that special file
/dev/stdin
if built for an OS that offers it, but since bash 2.04 will work around that file's absence on systems that do not support it.)pilcrow's answer provides an elegant solution; this is an explanation of why the OP's approach didn't work.
The main problem with the OP's approach was the attempt to assign to positional parameter
$1
with$1=...
, which won't work.The LHS is expanded by the shell to the value of
$1
, and the result is interpreted as the name of the variable to assign to - clearly, not the intent.The only way to assign to
$1
in bash is via theset
builtin. The caveat is thatset
invariably sets all positional parameters, so you have to include the other ones as well, if any.(If you expect only at most 1 argument,
set -- "${1:-/dev/stdin}"
will do.)The above also corrects a secondary problem with the OP's approach: the attempt to store the contents rather than the filename of stdin in
$1
, since<
is used.${1:-/dev/stdin}
is an application of bash parameter expansion that says: return the value of$1
, unless$1
is undefined (no argument was passed) or its value is the empty string (""
or''
was passed). The variation${1-/dev/stdin}
(no:
) would only return/dev/stdin
if$1
is undefined (if it contains any value, even the empty string, it would be returned).If we put it all together:
But, of course, the much simpler approach would be to use
${1:-/dev/stdin}
as the filename directly:or, via an intermediate variable:
For a general case of wanting to read a value from stdin when a parameter is missing, this will work.
script.sh
Here is my version of script:
If file is not present in the argument, read the from standard input.
See more examples: How to read from file or stdin in bash? at stackoverflow SE
Variables are assigned a value by
Var=Value
and that variable is used by e.g.echo $Var
. In your case, that would amount towhen assigning the standard input. However, I do not think that variable names are allowed to start with a digit character. See the question bash read from file or stdin for ways to solve this.