0

My script reads a list of ".bag" files from a textfile supplied as an argument. and does something with each one. (for clarity, I have omitted most of the "stuff")

while IFS= read -r bag
do

    echo Extracting from $bag

    # Play the script for saving the images
    python2 extract_imgs.py --image_topics "$image_topics" --basepath "extracted_imgs/$bag_name" &
    extract_imgs_PID=$!

    # play the bag file
    rosbag play -r 10 $bag

    echo rosbag play returned: $?
    echo finished playing $bag

    # kill the subscribe node
    kill $extract_imgs_PID

done < $1

If I comment out the rosbag play -r 10 $bag line, this script behaves as I expect: It reads each line from $1 and runs an iteration of the loop with that line set as $bag.

But with the 'rosbag play -r 10 $bag' line, it works correctly for the first line, but then exits the loop and finishes. Why? the return status of rosbag play is 0. How can I get this script to run the rosbag play command and then continue looping over the lines of the input file?

ezekiel
  • 427
  • 5
  • 20
  • 2
    Probably `rosbag` is reading from stdin, stealing lines from `read`. See [Why redirect stdin inside a while read loop in bash?](https://stackoverflow.com/q/41650892/4518341) and [Shell script while read line loop stops after the first line](https://stackoverflow.com/q/13800225/4518341) – wjandrea May 18 '20 at 13:55
  • Also [BashFAQ #89: I'm reading a file line by line and running ssh or ffmpeg, only the first line gets processed!](https://mywiki.wooledge.org/BashFAQ/089) – Gordon Davisson May 18 '20 at 13:59
  • yep that was it, thankyou! – ezekiel May 18 '20 at 14:22
  • Does this answer your question? [Shell script while read line loop stops after the first line](https://stackoverflow.com/questions/13800225/shell-script-while-read-line-loop-stops-after-the-first-line) – wjandrea May 18 '20 at 14:36
  • that is the same problem but the Accepted Answer does not apply here, as there is no such "-n" flag for rosbag play. – ezekiel May 18 '20 at 15:09
  • See the [second answer](https://stackoverflow.com/a/55334788/4518341) then – wjandrea May 18 '20 at 20:04
  • yes, the second answer is the solution. – ezekiel May 18 '20 at 23:33

2 Answers2

0

The problem was the same as:

I'm reading a file line by line and running ssh or ffmpeg, only the first line gets processed!

so the solution was to redirect stdin:

rosbag play -r 10 $bag </dev/null
ezekiel
  • 427
  • 5
  • 20
-1

I will offer a solution, with the disclaimer that the solutions which I offer normally don't get very well received around here; but anyway...

#!/bin/sh -x

init() {
cat >> edprint+.txt << EOF
1p
q
EOF

cat >> edpop+.txt << EOF
1d
wq
EOF

next
}

next() {
[[ -s stack ]] && main
end
}

main() {
filename=$(ed -s stack < edprint+.txt)
python2 extract_imgs.py --image_topics "$image_topics" --basepath "extracted_imgs/$bag_name" &
    extract_imgs_PID=$!
rosbag play -r 10 ${filename}
echo "rosbag play returned: $?"
echo "finished playing ${filename}"
ed -s stack < edpop+.txt
next
}

end() {
rm -v ./edpop+.txt
rm -v ./edprint+.txt
exit 0
}

init

The above script uses the text file containing the names as a stack. Ed is used to put each file name into a variable, against which you can then run whatever commands you desire. At the end of the main function, Ed is called again to remove the top line from the file; and a loop between two functions (main and next) iterates until the text file is empty, at which point the two Ed commands files are deleted, and the script terminates.

petrus4
  • 616
  • 4
  • 7