shell script strangeness

I made a small script to convert some mpegs to a more portable format

Code:
#!/bin/sh

usage () {
	echo "usage: $0 [-f file] [-dvh]"
}

help () {
	usage
	echo " -f <file>
 -d     dryrun
 -v     verbose
 -h     help
"
exit
}
trap "exit 1" 0 1 2 15

system () {
  test -z $verbose || echo "+ $*" 1>&2
  test -z $dryrun || return
  eval "$@"
}
while [ x"$1" != x"" ]
do
	case  $1 in
		-f)             file=$2; shift;;
		-v)             verbose=1;;
		-d)             dryrun=1;;
		-h)             help;exit;;
	esac
	shift
done

test -z "$file" && help;
test -f "$file" || help

grep -v '^#' $file | \
while read a b 
do
 	cmd="fmpeg -i $a -ac 2 -ar 48000 -b 1000k -s cif $b.m4v"
	system $cmd
done

I feed the script with a file like this

Code:
gong:/medialib/tc# cat infile.txt
#/medialib/teapot/3150_20091012215900.mpg file-1
/medialib/teapot/2150_20091026215900.mpg file-2
/medialib/teapot/3150_20091102215900.mpg file-3
/medialib/teapot/3150_20091110215900.mpg file-4

Testrun

Code:
gong:/medialib/tc# ./trans.sh -v -d -f infile.txt 
+ fmpeg -i /medialib/teapot/2150_20091026215900.mpg -ac 2 -ar 48000 -b 1000k -s cif file-2.m4v
+ fmpeg -i /medialib/teapot/3150_20091102215900.mpg -ac 2 -ar 48000 -b 1000k -s cif file-3.m4v
+ fmpeg -i /medialib/teapot/3150_20091110215900.mpg -ac 2 -ar 48000 -b 1000k -s cif file-4.m4v

However when I ommit '-d', ffmpeg runs only once and then the script exits silently

Code:
gong:/medialib/tc# ./trans.sh -f infile.txt -v 
+ fmpeg -i /medialib/teapot/2150_20091026215900.mpg -ac 2 -ar 48000 -b 1000k -s cif file-2.m4v
FFmpeg version 0.5, Copyright (c) 2000-2009 Fabrice Bellard, et al.

 .... plenty of output as ffmpeg does it's job

gong:/medialib/tc#

Does anyone see something obviously stupid I'm doing, or otherwise have an explanation for this behaviour?
 
The bourne shell doesn't have a 'system' command. Remove the 'system' from your script.

Scratch that, I didn't notice the function. I'm betting the error is in there though.

Looks like the 'test -z $dryrun || return' doesn't do what you expect ;)
 
Funny thing is, if I replace ffmpeg with a bogus cmd it does loop
Code:
gnome:/medialib/tc# ./trans.sh -v -f infile.txt 
+ fmpeg -i /medialib/teapot/2150_20091026215900.mpg -ac 2 -ar 48000 -b 1000k -s cif file-2.m4v
fmpeg: not found
+ fmpeg -i /medialib/teapot/3150_20091102215900.mpg -ac 2 -ar 48000 -b 1000k -s cif file-3.m4v
fmpeg: not found
+ fmpeg -i /medialib/teapot/3150_20091110215900.mpg -ac 2 -ar 48000 -b 1000k -s cif file-4.m4v
fmpeg: not found

And, btw -d work as expected, witness this
Code:
gnome:/medialib/tc# ./trans.sh -v -f infile.txt -d
+ fmpeg -i /medialib/teapot/2150_20091026215900.mpg -ac 2 -ar 48000 -b 1000k -s cif file-2.m4v
+ fmpeg -i /medialib/teapot/3150_20091102215900.mpg -ac 2 -ar 48000 -b 1000k -s cif file-3.m4v
+ fmpeg -i /medialib/teapot/3150_20091110215900.mpg -ac 2 -ar 48000 -b 1000k -s cif file-4.m4v
 
jalla said:
And, btw -d work as expected, witness this
Now have another close look at your code.. See what happens when $dryrun isn't defined ;)
 
aragon said:
Are you pasting us the same script? What you pasted seems to work here...

100%
I pasted it back and compared them.

As it happens the script works with anything I throw at it except ffmpeg.
 
SirDice said:
Now have another close look at your code.. See what happens when $dryrun isn't defined ;)

When $dryrun isn't defined the cmd is executed. Just the way I want it.
 
You can always run your shell script with the -x option. I use it quite a lot to see what's going on.
 
SirDice said:
You can always run your shell script with the -x option. I use it quite a lot to see what's going on.

Good point. Unfortunately it makes me none the wiser. Here's the end of a run with -x. It shows a normal end of the ffmpeg cmd, then the next iteration of the while loop (read a b), and then an immediate exit 1.

Code:
...
[libx264 @ 0x806548a10]slice I:12747 Avg QP:20.52  size: 17168
[libx264 @ 0x806548a10]slice P:140164 Avg QP:22.32  size:  3990
[libx264 @ 0x806548a10]mb I  I16..4:  7.7%  0.0% 92.3%
[libx264 @ 0x806548a10]mb P  I16..4:  3.4%  0.0%  0.0%  P16..4: 83.6%  0.0%  0.0%  0.0%  0.0%    skip:13.0%
[libx264 @ 0x806548a10]final ratefactor: 16.60
[libx264 @ 0x806548a10]SSIM Mean Y:0.9747017
[libx264 @ 0x806548a10]kb/s:1017.8
+ read a b
+ exit 1
 
Sorry, I think it might actually be your trap on signal 2 that's causing this. Anyhow, experiment with that line as it's the only place where "exit 1" can be getting called.
 
aragon said:
Sorry, I think it might actually be your trap on signal 2 that's causing this. Anyhow, experiment with that line as it's the only place where "exit 1" can be getting called.

No it's not the trap, but I nailed it in the end anyway. It's actually ffmpeg that eats the rest of infile.
Remember when ffmpeg starts processing it says

Press [q] to stop encoding

The problem is clearly demonstrated with a slightly modified infile (add some q's in there)

Code:
#/medialib/teapot/3150_20091012215900.mpg qfile-1
#/medialib/teapot/2150_20091026215900.mpg qfile-2
/medialib/teapot/3150_20091102215900.mpg qfile-3
/medialib/teapot/3150_20091110215900.mpg qfile-4

Then another run of the script (with ffmpeg output redirected for clarity)

Code:
gong:/medialib/tc# sh -x trans.sh -f infile.txt
+ [ x-f != x ]
+ file=infile.txt
+ shift
+ shift
+ [ x != x ]
+ test -z infile.txt
+ test -f infile.txt
+ grep -v '^#' infile.txt
+ read a b
+ cmd='ffmpeg -i /medialib/teapot/3150_20091102215900.mpg -ac 2 -ar 48000 -b 1000k -s cif -t 60 -y qfile-3.m4v > qfile-3.out 2>&1'
+ system ffmpeg -i /medialib/teapot/3150_20091102215900.mpg -ac 2 -ar 48000 -b 1000k -s cif -t 60 -y qfile-3.m4v '>' qfile-3.out '2>&1'
+ test -z
+ test -z
+ eval ffmpeg -i /medialib/teapot/3150_20091102215900.mpg -ac 2 -ar 48000 -b 1000k -s cif -t 60 -y qfile-3.m4v '>' qfile-3.out '2>&1'
+ ffmpeg -i /medialib/teapot/3150_20091102215900.mpg -ac 2 -ar 48000 -b 1000k -s cif -t 60 -y qfile-3.m4v
+ read a b
+ cmd='ffmpeg -i file-4 -ac 2 -ar 48000 -b 1000k -s cif -t 60 -y .m4v > .out 2>&1'
+ system ffmpeg -i file-4 -ac 2 -ar 48000 -b 1000k -s cif -t 60 -y .m4v '>' .out '2>&1'
+ test -z
+ test -z
+ eval ffmpeg -i file-4 -ac 2 -ar 48000 -b 1000k -s cif -t 60 -y .m4v '>' .out '2>&1'
+ ffmpeg -i file-4 -ac 2 -ar 48000 -b 1000k -s cif -t 60 -y .m4v
+ read a b
gong:/medialib/tc#

The first invocation of ffmpeg continues to read characters from stdin up to the first 'q' and quits. Then the next round of the loop reads whats left, which is only 'file4'.

So the while-loop has to go. Here's a replacement to make the script work

Code:
IFS='
'
for l in `grep -v '^#' $file`
do
        a=`echo $l | cut -d " " -f 1`
        b=`echo $l | cut -d " " -f 2`
        cmd="ffmpeg -i $a -ac 2 -ar 48000 -b 1000k -s cif -t 60 -y $b.m4v > $b.out 2>&1"
        system $cmd
done
 
Back
Top