I have this code:
#!/bin/bash
# ~/test.sh
if [[ -p /dev/stdin ]]; then
var="-"
else
var="$1"
fi
l=$(cat -n "$var" | wc -l)
c=$(cat -n "$var" | wc -m)
echo l=$l
echo c=$c
If i run:
$ ./test.sh file.txt
l=73
c=4909 # it is correct
but if
cat file.txt | ./test.sh
l=73
c=0 #why i have 0???
i don't understand why i have c=0
cat file.txt | cat -n - | wc -c
works; so what's the problem with my code?
what am I doing wrong?
how can i make it work properly?
When you pipe rather than open a file, the difference is that the piped-in or stdin
is a stream (no seek back to start).
l=$(cat -n "$var" | wc -l)
Consumes the whole stream to count lines.
When it reaches:
c=$(cat -n "$var" | wc -m)
The stdin
stream has all been consumed by the previous counting of lines. It has nothing to count left, thus returning 0
.
Fortunately wc
can do both on the same run, and then you can read the result values like this:
#!/usr/bin/env bash
var=${1--}
if [ -p /dev/stdin ]; then
if [ $# -ge 1 ]; then
printf %s\\n 'Need either stdin or filename argument (not both)!' >&2
exit 1
fi
elif [ $# -ne 1 ]; then
printf %s\\n 'Need stdin or a single filename argument!' >&2
exit 1
fi
read -r l c _ < <(wc -lm -- "$var")
printf 'l=%d\nc=%d\n' "$l" "$c"