How can I use the value from a pipe in the test program?
It doesn't answer your question about pipes, but you can rearrange:
test $(ls -l | wc -l) -eq 1 && echo "worked"
And there's a few solutions on SO, this being the nicest:
ls -l | wc -l | { read wc; test $wc -eq 7 && echo "woohoo"; }
If you are using Bash, you probably want to research the PIPESTATUS variable. As noted in the Bash reference guide, PIPESTATUS is
An array variable (see Arrays) containing a list of exit status values from the processes in the most-recently-executed foreground pipeline (which may contain only a single command).
We can find out what the exit codes were for this pipeline with PIPESTATUS:
dmesg | grep -iw 'nnse' | wc -l
If you now query the array variable, you get the exit statuses referring to the commands used in the pipeline:
echo ${PIPESTATUS[@]}
0 1 0
(In an indexed array, those exit codes above are represented by 0 1 and 2 in the array as arrays always start at 0 in Bash.)
Here we see the second command returned 1, and the rest 0; however, wc -l
returns 0 if there are zero matches, which is not an error. Failure is represented with a non-zero value, and there are other error values such as 127 which is command not found, and yet more codes which may be specific to the program concerned.
If you want to see what a particular command's exit code in the pipeline was, you can just access that value. The grep command was the second command in the pipeline above, but as arrays start from 0, we need entry one.
So to find out the grep command's exit code, run the above pipeline again (as the content of PIPESTATUS will have been exhausted if you have run echo ${PIPESTATUS[@]}
) and then execute the command below, which will return 1 (the exit code):
echo ${PIPESTATUS[1]}
1
In a script, make sure the pipeline has finished executing before you seek the contents of the PIPESTATUS array variable.
For an example of interesting use of the PIPESTATUS array variable, see this answer regarding combining Bash command grouping and pipe status. You could test the array variable in the way suggested by Gilles in the comments, although you will first need to run the pipeline again:
dmesg | grep -iw 'nnse' | wc -l
[ ${PIPESTATUS[1]} -eq 1 ] && do_something_here
This is just a fragment, as I don't know what sort of script you are intending, but I hope knowing about PIPESTATUS may be of some use for you. There are many Bash array variables like PIPESTATUS that can be extremely useful; see the Bash reference guide for the whole list, and the other Stackexchange sites for examples of their usage.
The simplest way is probably to use xargs:
wc -l | xargs -I % test % -eq 1
This doesn't cover every test
case, but if you can use a regular expression, and grep
the piped string, it's pretty straight forward because grep
is test
-like in that it has a non-zero exit when no match is found
cat file | wc -l | grep -qE '^\s*1\s*$'
Extended regular expressions allow you to cover many cases with this technique. For giggles, a test case:
for i in 1 11 '' foo; do
if echo $i | grep -qE '^\s*1\s*$'; then
echo "'$i' matched"
else
echo "'$i' didn't match."
fi
done
outputs:
'1' matched
'11' didn't match.
'' didn't match.
'foo' didn't match.