Question

I have a bunch of AVI's that I'd like to reprocess to h264 MKVs. The command I'm trying to use is:

find . -name "*.avi" | xargs -I '{}' ffmpeg -i {} -vcodec libx264 `echo {} | sed 's/avi/mkv/'`

However, it does not work as expected. Adding -t to xargs shows that the command being run is (given a directory with file1.avi)

ffmpeg ./file1.avi -vcodec libx264 ./file1.avi

I'm not sure why the sed command isn't getting processed correctly. ffmpeg fails because it does not overwrite by default.

The AVIs are all in sub-directories so I don't really want to do a for loop for each subfolder and find / xargs would be a much better solution. Also, I don't really want to rename everything after this is done.

Was it helpful?

Solution

The reason why this is not working is because everything between ` ` is executed before the xargs execution. But if you quote it in ' ', then it is going to be passed correctly, but xargs is not going to parse or expand it.

But you can pipe to the bash function!

convertFile() {
    while read -r filename; do
        newFilename="${filename:0:-3}mkv"
        ffmpeg "$filename" -vcodec libx264 "$newFilename"
    done
}

find . -name "*.avi" | convertFile

Please note that instead of sed I am using bash string manipulations. The reason for that is that your file can sometimes contain avi word inside, like gravity. That is why more fail-proof way was used.

OTHER TIPS

find *.avi | while read f; do
    ffmpeg "$f" -vcodec libx264 "${f%.avi}.mkv"
done

and i split the lines to not scare people, but in real life it'd be

find *.avi|while read f;do ffmpeg "$f" -vcodec libx264 "${f%.avi}.mkv"; done

because this is one-liner territory.

You can use the following command instead :

find *.avi | awk '{print "\""$0"\"", "-vodec libx264","\""$0"\""}'  | sed 's/\(.*\)avi\"$/\1mkv\"/g' | xargs ffmpeg -i

Of course this has a lot of escape characters. It isn't a script, it's a command-line...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top