Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Following command tells me the length of mp4 video files:

find -type f -name "*.mp4" -print0 | \
   xargs -0  mplayer -vo dummy -ao dummy -identify 2>/dev/null | \
   perl -nle '/ID_LENGTH=([0-9\.]+)/ && ($t +=$1) && printf "%02d:%02d:%02d\n",$t/3600,$t/60%60,$t%60' | \
   tail -n 1

Can someone parse it to a Linux beginner and explain why it is the way it is?

It would also be helpful to know how to use it again and again without retyping it or through copy-and-paste.

share|improve this question
    
For the record, you can also get the duration (in seconds) of a mp4 file or any audio/video file with exiftool -p '$Duration#' file.mp4 –  Stéphane Chazelas Jan 25 '13 at 21:56
    
@Stephane You would have to tweak a little bit more to get the same output (i.e. the total length of all mp4 files). –  xyz Jan 26 '13 at 0:06

1 Answer 1

find -type f -name "*.mp4" -print0

Recursively search the current directory for normal files whose names end with .mp4 and print their relative path names, separated by null bytes. -print0 is safer than -print here, because newlines are valid characters in a filename. find(1)

| xargs -0

Use the input as arguments to the next command. Input is null-separated. xargs(1)

mplayer -vo dummy -ao dummy -identify 2>/dev/null

This is the command that xargs is running. Using dummy video and audio drivers, show file parameters in an easily parseable format. Discard any output from STDERR. mplayer(1)

| perl -nle

Pipe the output to Perl. Perl will read lines of input into the $_ variable, stripping newlines from the end. perlrun(1)

/ID_LENGTH=([0-9\.]+)/

If the line matches this regular expression, capture the number following "ID_LENGTH=",

&& ($t +=$1)

then increase the variable $t by the number captured in the first match,

&& printf "%02d:%02d:%02d\n",$t/3600,$t/60%60,$t%60'

and calculate hours, minutes, and seconds from $t, which is a count of seconds. Because of the -l in the perl invocation, a newline is added automatically to print statements, but not printf, so the format string contains one ("\n").

| tail -n 1

Only print the last line of output. tail(1)

To make this pipeline into a single command, you can create a shell function in your .bashrc or whatever rc-file your shell uses. Here's an example:

vid_lengths() {
  find -type f -name "*.mp4" -print0 \
    | xargs -0  mplayer -vo dummy -ao dummy -identify 2>/dev/null \
    | perl -nle '/ID_LENGTH=([0-9\.]+)/ && ($t +=$1) && printf "%02d:%02d:%02d\n",$t/3600,$t/60%60,$t%60' \
    | tail -n 1
}
share|improve this answer
    
@AdrianPronk You're right, and I should have caught that. Corrected. –  bonsaiviking Jan 30 '13 at 3:50

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.