tags:

views:

109

answers:

5

I'm trying to write my first semi advanced bash script that will take input in the form of a filename referring to an avi video, send it to ffmpeg to convert to a mp4 (preserving the original name) and then hand it off to MP4Box.

The below is pretty much what I'm doing...

#!/usr/bin/bash
ffmpeg -i $0 -acodec libfaac -ab 128k -ac 2 -vcodec libx264 -vpre hq -crf 22 -threads 0 ($0).mp4
MP4Box -inter 500 ($0).mp4
  • Is there some sort of try/catch I can do for the first program invocation to make sure MP4Box gets workable input?
  • Should I even bother with error catching at all, should I instead rely on the programs themselves to do this for me?
+1  A: 

Yes - you should worry about the errors and it's really not a big problem to do it - all you need to do is check the exit code of the application you executed - as a rule if everything went well the application should return an exit code equal to zero - take a look here if you need more details too: http://tldp.org/LDP/abs/html/exit-status.html

lskdf      # Unrecognized command.
echo $?    # Non-zero exit status returned because command failed to execute.
RnR
A: 

If ffmpeg is a good citizen, it will return an exit code of 0 on success and some other value on failure.

"$?" is a special bash construct that tells the return code of the last executed process. After the ffmpeg line you can check "$?" against non-zero values and exit in error.

diciu
+3  A: 

On the whole you can check the return code to determine the result of a command. You can get the return code of the previously executed command using the special variable $?. Beware that it's update after every command so use it to set another variable. For example RC = $?. Return codes are normally 0 for success and non-zero for failures. Specific non zero return codes may indicate particular types of failure. Check the man page of your command to find out exactly how to interpret them. Once you have the return code you can use it to branch. For example:

ffmpeg <your args>
RC=$?
if [ "${RC}" -ne "0" ]; then
    # Do something to handle the error.
else
    # Everything was ok.
fi
Tom Duckering
+4  A: 

One quick way to make the execution of one program dependent on the success of another is to use &&. (the commands below are all pseudo-code)

first-cmd && second-cmd

In this case second-cmd will only be executed if first-cmd returns true.

Likewise, you can test for failure and take appropriate action using ||

bad-cmd || echo "failed"

You can combine them in various ways:

good-cmd && echo "succeeded" || echo "failed"

bad-cmd || {
    recovery-cmd || 
    echo "recovery failed && 
    echo "recovered"
}

Of course, it's often clearer to use the special variable $? that others have noted.

You will often want to redirect error messages to /dev/null or capture them in a variable.

bad-cmd 2>/dev/null               # send error message to the bit bucket
var=$(good-cmd)                   # capture stdout
var=$(bad-cmd 2>&1)               # capture stdout and stderr
var=$(bad-cmd 2>&1 >/dev/null)    # capture only stderr

Then you can process the text of the error to obtain additional information for conditional action in your code.

See: Capture output in a variable and How can I redirect stderr to a pipe?

Dennis Williamson
A: 

You can run the shell with -e, or put the command set -e in your script. This will cause the script to terminate if any of the commands returns non-zero exit status.

If you need to run a command where you dont want a non-zero exit to cause the script to terminate, append || true to the command.

camh