1

I wrote the script that has to convert *.avi files to mp4 format. However "while" loop stops after first iteration.

#!/bin/bash
shopt -s lastpipe

cd <some_directory>

find . -name *.avi -type f |
  while read -r avi
    do
      /usr/bin/HandBrakeCLI -i "${avi}" -o "${avi%.avi}.mp4" -f mp4 -m -O -e x264 -q 20 --vfr \
#      &> /dev/null
      if [ "$?" -eq 0 ]
        then
          echo "${avi} was converted successfully"
          rm "${avi}"
        else
          echo "${avi} was not converted"
          break
      fi
    done 
user139980
  • 11
  • 2

2 Answers2

1

This part is wrong: find . -name *.avi -type f

The shell is expanding the wildcard before find starts, so the find command looks like:

find . -name a.avi b.avi.c.avi d.avi ... -type f

I'm surprised you didn't notice an error message, like "find: paths must precede expression: b.avi"

You need to protect the asterisk from the shell so find can to its own expansion. Pick one of

find . -name \*.avi -type f
find . -name '*.avi' -type f

You don't mention if you're on a GNU system or not. You're while loop is at risk of being tripped up by filenames with leading or trailing whitespace. Try this:

find . -name \*.avi -type f -print0 | while read -rd '' avi; do ...
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
  • you forgot to set IFS in order to keep leading/trailing whitespaces: while IFS= read -rd '' avi; do ... – lihao Aug 09 '14 at 03:25
0

HandBrakeCLI could also be reading input that it makes your loop end after the first instance is called. Since you're using bash, you can use process substitution with redirected input to another file descriptor. In this example with use 4:

while read -ru 4 avi; do
    ...
done 4< <(exec find . -name *.avi -type f)

My preferred version too is to use readarray. It's quite enough if you don't target irregular filenames where they have newlines:

readarray -t files < <(exec find . -name *.avi -type f)
for avi in "${files[@]}"; do
    ...
done

Another way perhaps is to redirect input of HandBrakeCLI to /dev/null:

</dev/null /usr/bin/HandBrakeCLI ...

Other suggestions:

  1. Quote your -name pattern: '*.avi'
  2. Use IFS= to prevent stripping of leading and trailing spaces: IFS= while read ...
konsolebox
  • 72,135
  • 12
  • 99
  • 105