Get the code to complete the process substitution with the pipeline in the while loop

The following script calls another program that reads its output in a while loop (see Bash - How to connect input to a while loop and save variables after the end of the loop ):

while read -r col0 col1; do
    # [...]
done < <(other_program [args ...])

How to check the exit code other_programto make sure that the loop was executed correctly?

+8
source share
4 answers

Note: ls -d / /nosuchused as an example below because it fails (exit code 1) while still producing stdout ( /) output (in addition to stderr output).

Bash v4.2 + solution:

ccarton , while , , , , .

Bash v4.2 + , lastpipe, , ;
ccarton, pipefail , $? :

shopt -s lastpipe  # run the last segment of a pipeline in the current shell
shopt -so pipefail # reflect a pipeline first failing command exit code in $?

ls -d / /nosuch | while read -r line; do 
  result=$line
done

echo "result: [$result]; exit code: $?"

( stderr ):

result: [/]; exit code: 1

, $result, while, , ls ( ) $?.


Bash v3 + :

ikkachu , . :

while read -r line || { ec=$line && break; }; do   # Note the `|| { ...; }` part.
    result=$line
done < <(ls -d / /nosuch; printf $?)               # Note the `; printf $?` part.

echo "result: [$result]; exit code: $ec"
  • $?, ls, \n (printf $?), read , ( 1), .

  • || ( $line) $ec .


, \n, :

while read -r line || 
  { [[ $line =~ ^(.*)/([0-9]+)$ ]] && ec=${BASH_REMATCH[2]} && line=${BASH_REMATCH[1]};
    [[ -n $line ]]; }
do
    result=$line
done < <(printf 'no trailing newline'; ls /nosuch; printf "/$?")

echo "result: [$result]; exit code: $ec"

( stderr ):

result: [no trailing newline]; exit code: 1
+4

. PID, wait PID.

#!/bin/bash
mkfifo pipe || exit 1
(echo foo ; exit 19)  > pipe &
pid=$!
while read x ; do echo "read: $x" ; done < pipe
wait $pid
echo "exit status of bg process: $?"
rm pipe

(.. , ), Bash PIPESTATUS, :

(echo foo ; exit 19) | while read x ; do 
  echo "read: $x" ; done; 
echo "status: ${PIPESTATUS[0]}" 
+8

bash pipefail .

set -o pipefail
other_program | while read x; do
        echo "Read: $x"
done || echo "Error: $?"
+2

- coproc ( 4.0 +).

coproc other_program [args ...]
while read -r -u ${COPROC[0]} col0 col1; do
    # [...]
done
wait $COPROC_PID || echo "Error exit status: $?"

coprocfrees you from having to configure the asynchrony and redirection of stdin / stdout, which you would need to do in equivalent mkfifo.

+1
source

Source: https://habr.com/ru/post/1016932/


All Articles