Iterate over the output of a command in bash without a subshell

13,561

You missed a <. Should be:

while read BLAH ; do echo $BLAH; done < <(sysctl -a 2>/dev/null | grep '\.rp_filter')

Think of <(sysctl -a 2>/dev/null | grep '\.rp_filter') being a file.

Share:
13,561

Related videos on Youtube

dribler
Author by

dribler

Real Name: Chris Francy I work as a Senior Network Analyst at Northwest Educational Service District #189 in the Technology Services department. The Technology Service department, in addition to supporting the staff at NWESD, provides network support services to 35 K-12 school districts in Northwest Washington region. In my free time, when I am not at work or answering questions, I play a lot of video games on the PC (Steam Profile).

Updated on September 17, 2022

Comments

  • dribler
    dribler almost 2 years

    I want to loop over the output of a command without creating a sub-shell or using a temporary file.

    The initial version of of my script looked like this, but this doesn't work since it creates a subshell, and the exit command terminates the subshell instead of the main script which is required. It is part of a much larger script to configure policy routing, and it is halt the execution if it detects a condition that will cause routing to fail.

    sysctl -a 2>/dev/null | grep '\.rp_filter' | while read -r -a RPSTAT ; do
    
      if [[ "0" != "${RPSTAT[2]}" ]] ; then
        echo >&2 "RP Filter must be disabled on all interfaces!"
        echo >&2 "The RP filter feature is incompatible with policy routing"
        exit 1
      fi
    done
    

    So one of the suggested alternatives is to use a command like this to avoid the subshell.

    while read BLAH ; do echo $BLAH; done </root/regularfile
    

    So it seems to me that I should also be able use a command like this to avoid the subshell and still get the output from the program I want.

    while read BLAH ; do echo $BLAH; done <(sysctl -a 2>/dev/null | grep '\.rp_filter')
    

    Unfortunately, using that command results in this error.

    -bash: syntax error near unexpected token `<(sysct ...
    

    I get really confused since this does work.

    cat <(sysctl -a 2>/dev/null | grep '\.rp_filter')
    

    I could save the output of that command to a temporary file, and use redirect the on the temporary file, but I wanted to avoid doing that.

    So why is the redirection giving me an error, and do I have any options other then creating a temporary file?

  • dribler
    dribler over 13 years
    Thanks a lot. Just for my edification, can point me at a man page, help, or web page, that documents this? I couldn't get Google to point me at anything useful while trying to search for this.
  • CurtainDog
    CurtainDog over 13 years
    Google "process substitution". e.g. tldp.org/LDP/abs/html/abs-guide.html#PROCESS-SUB
  • ewindisch
    ewindisch over 13 years
    It should be noted that the <() substitution uses file descriptors and on some operating systems will transparently create & use temporary files.
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' over 13 years
    @Zoredache: Simply search for <( in the bash manual (it's under “process substitution”).
  • dribler
    dribler over 13 years
    @ewindisch, if a tool transparently creates a tempfile that is fine, I just didn't want to manually create one, when I was pretty sure I didn't need to.