How can I get duration of all video files in a folder containing multiple subfolders?
I have a folder named tutorials. Inside it, there are about 15 folders each containing about 15-20 .mp4
video files. I want to get the total duration of all the files present in the folder tutorials
. This is the code I have written so far:
for d in ~/Videos/tutorials/*; do
if [ -d "$d" ]; then
exiftool -n -q -p '${Duration;our $sum;$_=ConvertDuration($sum+=$_)}' ./*.mp4| tail -n1
fi
done
The above code, when executed, gives an error File not found: ./*.mp4
for each of the subfolders present inside tutorials. However, when the line
exiftool -n -q -p '${Duration;our $sum;$_=ConvertDuration($sum+=$_)}' ./*.mp4| tail -n1
is executed individually inside each sub-folders, I am able to get the correct output.
What changes should I make in the above code to get it working?
Solution 1:
You could use this instead which finds you all your mp4's in a specific folder and all subfolders and sums their duration to a total. This takes also care if they have special characters like a space etc.
find ~/Videos/tutorials/ -name "*.mp4" -printf "\"%p\" " | xargs exiftool -n -q -p '${Duration;our $sum;$_=ConvertDuration($sum+=$_)}' | tail -n 1
To see the totals of every subfolder aswell
#!/bin/bash
SEARCHPATH=~/Videos/tutorials
echo "## TOTAL OF EVERY MP4"
find $SEARCHPATH -name "*.mp4" -printf "\"%p\" " | xargs exiftool -n -q -p '${Duration;our $sum;$_=ConvertDuration($sum+=$_)}' | tail -n 1
find $SEARCHPATH -type d > /tmp/allFolders.txt
while read -r; do
echo "## TOTAL OF $REPLY"
find "$REPLY" -maxdepth 1 -name "*.mp4" -printf "\"%p\" " | xargs exiftool -n -q -p '${Duration;our $sum;$_=ConvertDuration($sum+=$_)}' | tail -n 1
done < /tmp/allFolders.txt
#cleanup
rm /tmp/allFolders.txt
Solution 2:
You should replace ./*.mp4
with "$d"/*.mp4
:
for d in ~/Videos/tutorials/*; do
if [ -d "$d" ]; then
exiftool -n -q -p '${Duration;our $sum;$_=ConvertDuration($sum+=$_)}' "$d"/*.mp4| tail -n1
fi
done
Your for loop is finding any directories in ~/Videos/tutorials/ and assigning its path to the value of the d
variable. That's the directory you want to check for mp4 files with exiftool, whereas you're telling exiftool to use the current directory with ./
.
Another approach would be to cd
to the directory each time, so your code would become:
for d in ~/Videos/tutorials/*; do
if [ -d "$d" ]; then
cd "$d"
exiftool -n -q -p '${Duration;our $sum;$_=ConvertDuration($sum+=$_)}' ./*.mp4| tail -n1
fi
done
The following approach can be used if you have troublesome filenames for some of the mp4 files, such as containing spaces. It saves the filenames into an array, and expands them quoted in the exiftool
command.
for d in ~/Videos/tutorials/*; do
if [ -d "$d" ]; then
cd "$d"
files=(./*.mp4)
exiftool -n -q -p '${Duration;our $sum;$_=ConvertDuration($sum+=$_)}' "${files[@]}"| tail -n1
fi
done