Skip to main content
added 875 characters in body
Source Link
Stéphane Chazelas
  • 584.6k
  • 96
  • 1.1k
  • 1.7k
#! /bin/sh -
i=0; while [ "$i" -lt 1000 ]; do
  cmdA
  cmdB > tempfile || continue
  cmdC < tempfile || break
  i=$((i + 1))
done
rm -f tempfile

If you can't litter the current directory with temp files, you could do:

#! /bin/sh -
i=0; while [ "$i" -lt 1000 ]; do
  cmdA 3>&- 4<&-
  tmp=$(mktemp) || exit
  exec 3> "$tmp" 4< "$tmp"
  rm -f "$tmp"
  cmdB >&3 3>&- 4<&- || continue
  cmdC <&4 3>&- 4<&- < tempfile || break
  i=$((i + 1))
done
exec 3>&- 4<&-
rm -f tempfile

Whatever you do, you'll need to store that output somewhere as you can't get the exit status of cmdB until it has terminated.

You could store it in memory instead. If cmdB's output is text, you could do:

#! /bin/sh -
i=0; while [ "$i" -lt 1000 ]; do
  cmdA
  output=$(cmdB > tempfile && echo .) || continue
  output=${output%.}
  printf %s "$output" | cmdC || break
  i=$((i + 1))
done

If printf is not built in your /bin/sh (for instance if you've installed mksh or yash and made it sh), that will fail for output larger than 128KiB.

Or you could use perl instead:

#! /usr/bin/perl
for ($i = 0; $i < 1000; $i++) {
  system "cmdA";
  $output = `cmdB`;
  next if $?;
  open TO_C, "|-", "cmdC" or last;
  print TO_C $output;
  close TO_C;
  last if $?;
}
#! /bin/sh -
i=0; while [ "$i" -lt 1000 ]; do
  cmdA
  cmdB > tempfile || continue
  cmdC < tempfile || break
  i=$((i + 1))
done
rm -f tempfile

If you can't litter the current directory with temp files, you could do:

#! /bin/sh -
i=0; while [ "$i" -lt 1000 ]; do
  cmdA
  tmp=$(mktemp) || exit
  exec 3> "$tmp" 4< "$tmp"
  rm -f "$tmp"
  cmdB >&3 3>&- 4<&- || continue
  cmdC <&4 3>&- 4<&- < tempfile || break
  i=$((i + 1))
done
exec 3>&- 4<&-
rm -f tempfile
#! /bin/sh -
i=0; while [ "$i" -lt 1000 ]; do
  cmdA
  cmdB > tempfile || continue
  cmdC < tempfile || break
  i=$((i + 1))
done
rm -f tempfile

If you can't litter the current directory with temp files, you could do:

#! /bin/sh -
i=0; while [ "$i" -lt 1000 ]; do
  cmdA 3>&- 4<&-
  tmp=$(mktemp) || exit
  exec 3> "$tmp" 4< "$tmp"
  rm -f "$tmp"
  cmdB >&3 3>&- 4<&- || continue
  cmdC <&4 3>&- 4<&- < tempfile || break
  i=$((i + 1))
done
exec 3>&- 4<&-
rm -f tempfile

Whatever you do, you'll need to store that output somewhere as you can't get the exit status of cmdB until it has terminated.

You could store it in memory instead. If cmdB's output is text, you could do:

#! /bin/sh -
i=0; while [ "$i" -lt 1000 ]; do
  cmdA
  output=$(cmdB > tempfile && echo .) || continue
  output=${output%.}
  printf %s "$output" | cmdC || break
  i=$((i + 1))
done

If printf is not built in your /bin/sh (for instance if you've installed mksh or yash and made it sh), that will fail for output larger than 128KiB.

Or you could use perl instead:

#! /usr/bin/perl
for ($i = 0; $i < 1000; $i++) {
  system "cmdA";
  $output = `cmdB`;
  next if $?;
  open TO_C, "|-", "cmdC" or last;
  print TO_C $output;
  close TO_C;
  last if $?;
}
Source Link
Stéphane Chazelas
  • 584.6k
  • 96
  • 1.1k
  • 1.7k

#! /bin/sh -
i=0; while [ "$i" -lt 1000 ]; do
  cmdA
  cmdB > tempfile || continue
  cmdC < tempfile || break
  i=$((i + 1))
done
rm -f tempfile

If you can't litter the current directory with temp files, you could do:

#! /bin/sh -
i=0; while [ "$i" -lt 1000 ]; do
  cmdA
  tmp=$(mktemp) || exit
  exec 3> "$tmp" 4< "$tmp"
  rm -f "$tmp"
  cmdB >&3 3>&- 4<&- || continue
  cmdC <&4 3>&- 4<&- < tempfile || break
  i=$((i + 1))
done
exec 3>&- 4<&-
rm -f tempfile