Your method is sound, you just need to nest it per folder.
find . -type d |while IFS= read dir; do
t=$(mediainfo '--Output=Video;%Duration%\n' "$dir"/*.mp4 | awk '
{ sum += $1 }
END {
secs = int(sum / 1000 + 0.5);
h = int(secs / 3600);
m = int((secs - h * 3600) / 60);
s = int(secs - h * 3600 - m * 60);
printf("%02d:%02d:%02d\n", h, m, s)
}') 2>/dev/null
if [ "$t" != "00:00:00" ]; then
echo "$dir: $t"
fi
done \
|sed -r 's:[^/]*/:--/:g; s:((--/)*)--/:\1-- :; s:--/:| :g; s:([| ]*)-:\1|-:'
To adapt this to output hours and minutes as you requested in the question, change the printf
statement to say printf "%dh%02.0fm", h, m + s/60
(this also rounds to the nearest minute).
I assume you already understand the mediainfo
and awk
commands since you supplied them, though I did change the millisecond conversion to be rounded. I've merely wrapped this in a find
call that looks at all children directories of the current path (change .
for another path) and loops through its output line by line (while IFS= read dir
will read each line, even if there is spacing in it, into $dir
. This will not work if you have linebreaks in your directory names).
Since the directory might not contain any .mp4 files, I've piped errors from the assignment to $t
to /dev/null and then run a test to ensure the time isn't 00:00:00
(change that to 0h00m
if you adapted the output). Then I print the directory and the time.
Finally, a sed
uses extended regular expressions (-r
) to convert this into a tree with four substitutions (s
):
- Convert each parent directory name to two dashes (keep the trailing slash for now)
- Remove the final trailing slash
- Any parent remaining should get a pipe and spaces
- Add interim pipes