Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I need to convert videos but I don't know where are they, so I need to find them. How can I give the result and an output file name to ffmpeg with xargs ? I already find out that I can construct the two parameter with the command
find . -iname "*.mov" -printf "%p %f\n"

I can't find anything related in the xargs manual. I want something like this:
find . -iname "*.mov" -printf "%p %f\n" | xargs ffmpeg -i {param1} -f flv {param2}

How can I do this ?

share|improve this question

6 Answers 6

up vote 1 down vote accepted

Something like this will do the trick and preserve full path, handle space, rename folder/movie.mov to folder/movie.flv, etc.

find . -name "*.mov" | while read movie;do
  ffmpeg -i "$movie" -f flv "${movie%.mov}.flv"
done

And if I misunderstood you and you want all the .flv movies in the current directory, use this one instead:

find . -name "*.mov" | while read movie;do
  ffmpeg -i "$movie" -f flv "$(basename "${movie%.mov}.flv")"
done
share|improve this answer
1  
If you want it as a oneliner, just put everything on one line. ;) –  Mattias Ahnberg Jan 8 '12 at 2:58

Not sure if you can or how to do that with xargs.

But something like this should work for you.

find . -iname "*.mov" -printf "%p %f\n" | while read -a HR ; do echo ffmpeg -i ${HR[0]} -f flv ${HR[1]} ;done
share|improve this answer
1  
This doesn't properly handle spaces in file names/paths, does it? –  Daniel Beck Jan 7 '12 at 17:05

The reason people use xargs in combination with find is that multiple file names will be passed to the same program invocation of whatever program xargs launches. For example, if find returns the files foo, bar, and baz, the following will run mv only once:

find sourceDir [...] -print0 | xargs -0 mv -t destDir

Effectively, it calls mv like the following:

mv -t destDir foo bar baz

If you don't need or want this behavior (as I assume is the case here), you can simply use find's -exec.


In this case, an easy solution would be to write a short shell script, like the following:

#!/usr/bin/env bash
[[ -f "$1" ]] || { echo "$1 not found" ; exit 1 ; }
P="$1"
F="$( basename $P )"
ffmpeg -i "$P" -f flv "$F"

Save as myffmpeg.sh and run chmod +x myffmpeg.sh. Then, run the following:

find . -iname "*.mov" -exec /path/to/myffmpeg.sh {} \;

This will invoke the shell script once for every file found. The shell script in turn extracts the file name from the full path, and calls ffmpeg with the appropriate arguments.

share|improve this answer

Why not simply move the options of the ffmpeg to fit the format of the results from the find command?

find . -iname "*.mov" -printf "%p %f\n" | xargs -r -n2 ffmpeg -f flv -i

Notice the addition of the -r option to xargs to prevent it from running ffmpeg if no .mov files are found.

I have added the -n2 option to xargs to limit the number of items xargs processes to two at a time. In this case, the items are the file path and the file name. If no -n option is set, xargs will process as many input items as possible in a single execution.

share|improve this answer
    
This won't work once more than one file is found AFAICT. –  Daniel Beck Jan 7 '12 at 17:59
    
This works only once for me too, but I dont understand why it stops after the first. Any idea ? –  Walkman Jan 7 '12 at 21:04
    
actually it doesnt work –  Walkman Jan 7 '12 at 21:25
    
Daniel-Beck and @Walkman were correct about the single execution. To solve that problem, I have edited this answer to limit the number of items xargs processes at a time via the -n2 option. Without the -n2, xargs executes only once if it can handle the number of input items it receives through the pipe. It also should be pointed out that this solution only works when file names and file paths do not include whitespace. –  ZaSter Jan 8 '12 at 2:16

You can run ffmpeg directly from the find command like this:

find . -iname "*.mov" -exec ffmpeg -i "%p" -f flv "%f" \;

Note the quotes around the parameters to ffmpeg, in case there are spaces in the filename, and the escaped semi-colon marks the end of the executed command.

share|improve this answer
    
Do you have documentation for the behaviour of -exec that also interprets printf formatting placeholders? –  Daniel Beck Jan 7 '12 at 13:23
    
Nope. Brain fart: I was thinking the %p and %f were find-things, not printf-things. I've voted for your answer. –  Randy Orrison Jan 7 '12 at 17:37

I did not get the solution I was expected, so I found out my own. @Daniel's answer is good, but it need a shell script. A one liner is quicker, and I like it better :) also simpler solution than writing a script.

I could use one argument and process it with basename and using sh -c

find . -iname "*.mov" -print0 | xargs -0 -i sh -c 'ffmpeg -i {} -f flv `basename {}`'

The -i tells to xargs to replace {} with the current argument.
Command output inside `` printed out to standard output (bash feature) so basename {} will be evaluated as the bare file name and printed out.
-0 for handling special file names properly, but you need to pass parameters with the -print0 option with find

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.