bash script : another set of eyes, please?
Ok, I'm at my wits end with a rather simple little script and no matter how many incantations of IFS/read fiddling I do, I can't figure it out.
It's basically a simple batch script that invokes ffmpeg on numerous files in a set location, converting them to another format. Problem is since some of them have come from Windows machines, there's every likelihood they could have spaces in them. I was lead to believe that using the -exec feature of find is the safest way to go about this, and it's what I've done in the past with success. Script in it's entirety is :- Code:
#!/bin/bash Code:
[howell@server1 bin]$ ./batchjob_ffmpegToMPEG2.sh Code:
24/01/2009 14:04:37 Processing file /home/video/batch/in/tompeg2/rotm06-001_1.vob Code:
24/01/2009 14:04:37 ================================================================================= |
can you please run it with "#!/bin/bash -x" instead of "#!/bin/bash" so we can see where this stuck?
|
Quote:
Code:
+ INPUT_DIR=/home/video/batch/in/tompeg2 |
Ok, an alternative, if someone can show me another way of running through a loop of files that's safe with spaces in the filenames, then I'm all ears.
|
Quote:
Code:
TMPFILE=`tempfile -s.deleteme` |
Ok, thanks for that, I've given it a whirl with some quick files with spaces in and it seems fine, which kerfuddles me somewhat as I'm sure the whole reason I went that route with 'find' was down to filename handling! I've got some other scripts that exhibit the same problem and do more complicated stuff, so I'll change those and give them a whirl and see how we get on.
Thanks again |
Simple expansion may work if you always enclose the variable in double quotes latter on:
for file in *.vob; do echo "$file"; done abc def.vob ab c.vob bc d.vob In this line: if [ -f "${FILE}" ] && [ -s "${FILE}" ]; then You might consider [ -f "${FILE}" -a -s "${FILE}" ]. && is normally used to run a second command depending on the success of the first command. In this line: find $INPUT_DIR -maxdepth 1 -print0 -type f -name '*' | while read -d $'\0' FILE; Could you explain the use of "$'\0'. I hadn't seen it before but the read command's "-d" argument seems to need it. Running this test, there is an unrelated wrinkle: find $INPUT_DIR -maxdepth 1 -print0 -type f -name '*' | while read -d $'\0' FILE; do echo file: "$FILE"; done file: testdir file: testdir/abc def.vob file: testdir/bc d.vob file: testdir/ab c.vob $INPUT_DIR/. is returned. Put `-type f' before `-print0'. Using capital letters for FILE is confusing to me because as I read it I have to remember that it isn't a constant. The convention is to use capital letters for constants like INPUT_DIR and small or mixed case letters for variables. Sorry I didn't get further into your script. |
It's one of those things where this script has laid around, organically growing over the past couple of years and, despite my commenting, I have clearly not put much history around why that find command is laid out the way it is. In truth, I've tried lots of things over time because quite clearly I just didn't know how it worked, so I googled here and there, saw how others had done it, and tried it myself. Clearly at some point I decided to use NUL as the field separator coming out of find, but why I didn't stick with LF I don't know. So I've put it back to a plain -print on the find command, and put read back to the default of just using LF too. I've kicked it off but it still does the same. I tried the above suggestion too, but still the same thing. Maybe this is something to do with ffmpeg maybe....
Code:
TMPFILE=/tmp/$$.tmp Code:
[howell@server1 tompeg2]$ batchjob_ffmpegToMPEG2-2.sh |
Quote:
Code:
IFS=" |
You may have misunderstood my post. It was the location of -print0 that could be a problem. It needs to be after the `-type f' argument. Otherwise, you are printing results before restricting the results to -type f. So, you will get the "." directory and any other directories as results which isn't what you want.
I checked in the abs-guide.pdf and found a usage of the $'\0nnn' construct. I just was curious if you knew about it. I've used `tr '\n' '\0' in the past to convert returns to nulls, but hadn't seen $'\0' before. It's the dollar sign that caught my eye, and I was hoping you knew why -d $'\0' works and -d '\0' doesn't. A construct you may find useful is: command1 && command2 || command3 for a pseudo code example: convert "$file1" "$file1.vob" && mv "${file1.vob" $DONE_DIR/ || mv "$file1" $ERR_DIR/ It the first command is executed, perform the second, otherwise the third. Good Luck. |
Quote:
Quote:
|
Quote:
From man bash Code:
QUOTING I prefixed all invocations of mv, rm, and ffmpeg with echo and the script ran as expected, which suggests that some command inside the loop is doing something funny. Does ffmpeg ever read from standard input? Does changing that line to Code:
ffmpeg -i "${FILE}" -target dvd "${OUTPUT_DIR}/${OUTPUT_FILENAME}" &> "/tmp/${FILENAME_NOEXT}_pass.log" < /dev/null |
Bear with me; I'll give it a run ;)
I'm working with the "while read FILE" version for now, as that exhibits the same behaviour as the original. If we can fix that one then I'll try the same process with the original script, and my other ones I have based on it, and see how it goes. I agree, playing around here it does seem that ffmpeg is doing something 'funny'. Trying your suggestion now... EDIT: Bingo, that's it :D ffmpeg doesn't sit held anywhere asking for input, but it does offer an abort keypress - could it be this? I'll go back and try it on my original scripts and see if that address the problem there too - I suspect it will ;) |
Thanks. I should have figured it out by trying "-d ''" instead of trying -d '\0'.
|
All times are GMT -5. The time now is 10:37 PM. |