On a Centos 6 machine, this works:
bash -c 'if grep -qP --line-buffered ".+" <(tail -n 1000 -F catalina.out) ; then echo "yes"; fi'
and this doesn't:
sh -c 'if grep -qP --line-buffered ".+" <(tail -n 1000 -F catalina.out) ; then echo "yes"; fi'
I get:
sh: -c: line 0: syntax error near unexpected token `('
sh: -c: line 0: `if grep -qP --line-buffered ".+" <(tail -n 1000 -F catalina.out) ; then echo "yes"; fi'
Nevermind the grep and tail. The problem is with the process substitution thingy: <(...)
Can someone tell me what sh does differently here?
[EDIT]
Thanks for the answers!
The problem arose while using capistrano for deployments. It defaults to using sh but I changed that to bash now.
The reason I couldn't do the normal piping is that when using tail -F | grep -q --line-buffered
, grep won't exit immediately after a match. There has to be one more edit to the file like echo "" >> catalina.out
and this was not acceptable in my situation.
The syntax
<(...)
is only supported by BASH.For any POSIX shell, use this approach:
i.e. move the stdin redirection in front of the
if
with a pipe. Theif
will pass stdin on to thegrep
.if tail ...| grep
won't work since theif
won't be able to see it'sthen
/fi
because the pipe separates processes.You should note that process substitution (
<(...)
) isn't specified by POSIX. So if you were runningbash
in POSIX mode by invoking it withsh
or saying:then you'd observe errors!
From the bash manual:
Also take note that if Bash is invoked with the name sh, it tries to mimic the startup behavior of historical versions of sh as closely as possible, while conforming to the POSIX standard as well.
If your sh is actually a link to bash, then this is what's causing that.
Running
sh --version; sh -c ': <(echo a)'
should give you enough info.