Friday, November 6, 2015

2 issues: bash Shell Expansion, Command substitution and Quoting | ffmpeg (or mplayer) and loops in a shell

So yesterday I needed to execute a loop, written in a bash shell, to convert a bunch of files using ffmpeg, and as always, I tried to handle spaces in file names. quoting variable names is obvious, and it should get you going, but the issue was that in one instance It just failed ... and that simple one-liner had a problem ... or two.

I had a variable holding the file name passed to "dirname" ; to get the path of containing directory of that file. but since I was using it this lovely one-liner and i was using, obviously, command substitution, that beutiful $() ; or "`" enclosing that would capture the output of a command and put it wherever you use this syntax.

So, the problem:

variable $filename holds a File name that has a space:

"./files/camera 1/file 1.mov"

that should be easy to handle, so dirname "$filename".

now we wrap it with the command substitution magic : $(dirname "filename"), and then when we are using the whole things in a line such as cp /$somevariable/$(diname "filename") ... well, I need to quote that again, right, sure thing, and inside it I'll escape the internal quotes, simple...

Escaping, using single quotes jumping in the air did not help. after substantial amount of time, i use a workaround, I run it separately to populate a variable and then quote them all in one... but there must be a workaround!

turns out its fairly easy, yet not really simple when it comes to bash syntax, it would be simply

"$(dirname "$filename")" or further quoting if needed such as " /$somevariable/$(diname "$filename")" ... but why does that work ? why is it not interpreted as "/somevariable/$(dirname "+$filename+")" ? as you would expect from any similar quoting ... turns out that command substitution is "special" ... and would handle that case! I was in pain ... I was glad I figured it out, its easy and clean, but really broke my heart. and to me it seems that this is the only case where something similar happens, otherwise, you'll need to wrestle with quoting and escaping.

I'm ashamed as I should have known this - and frankly I probably did, back when I was doing everything using bash - when usually moaning while telling how adorable bash is; I decided to write this down, hope it'll help someone out.

Now, another issue was there, the script always processed the first line it was fed and then stopped, I was puzzled, echoing the commands instead of executing them demonstrated the desired behaviour, but not when executing them. luckily I had a vague memory of a similar behaviour in mplayer; so what happened is that i was feeding the lines to be processed to a while loop reading from stdin; and ffmpeg and mplayer both keep reading from stdin probably expecting control instructions from the keyboard as it assumes its being run in an interactive shell. so the workaround was simple, but I'm not sure why not present in ffmpeg/avconv man pages, but you can read about it here as well. its to add the option "-nostdin" to the ffmpeg command.

On the Eastern shores of the Mediterranean lies a few "states" that are openly racist and promote segregation and spreads hate; ISIS, JSIL and SA ... and probably Iran


No comments: