I've a huge number of png files, which are named the following way: PREFIX_00000000.png
.
These files come from extracting frames from video files using ffmpeg -skip_frame nokey -i ORIGINALVIDEO.MP4 -vsync vfr -frame_pts true -r 1000 FRAMES_%d.png
which outputs files like:
FRAMES_15416721.png
FRAMES_26708343.png
FRAMES_38000000.png
FRAMES_49291677.png
FRAMES_60583335.png
FRAMES_71875085.png
(I came up with this by this answer. )
PREFIX_
is a fixed string and is followed by eight digits. Till now the video files are 24h max – which brings me to, 86400000ms (8 digits).
Maybe the video files will longer – thus I'm looking for a solution which could be changed to any number of digits. These numbers represent milliseconds (Since the beginning of the video file / representing the time into the video).
Now i'm searching for a way to convert the filename from the given format to the format PREFIX_HH:mm:ss.fff.png
. (String, followed by Hour:Minute:Second.Millisecond). So a file named FRAMES_49291677.png
would become FRAMES_13:41:31.677.png
.
Sample values would be the following. (I added examples for >24h as well.)
Input:
PREFIX_1.png
PREFIX_000000001.png
PREFIX_1012.png
PREFIX_00001012.png
PREFIX_12106.png
PREFIX_000012106.png
PREFIX_725463.png
PREFIX_00725463.png
PREFIX_1204242.png
PREFIX_001204242.png
PREFIX_9864336.png
PREFIX_09864336.png
PREFIX_36012486.png
PREFIX_036012486.png
PREFIX_49291677.png
PREFIX_049291677.png
PREFIX_86400000.png
PREFIX_086400000.png
PREFIX_113744568.png
PREFIX_261736874.png
Output:
PREFIX_00:00:00.001.png
PREFIX_00:00:00.001.png
PREFIX_00:00:01.012.png
PREFIX_00:00:01.012.png
PREFIX_00:00:12.106.png
PREFIX_00:00:12.106.png
PREFIX_00:02:05.463.png
PREFIX_00:02:05.463.png
PREFIX_00:20:04.242.png
PREFIX_00:20:04.242.png
PREFIX_02:44:30.336.png
PREFIX_02:44:30.336.png
PREFIX_10:00:12.486.png
PREFIX_10:00:12.486.png
PREFIX_13:41:31.677.png
PREFIX_13:41:31.677.png
PREFIX_24:00:00.000.png
PREFIX_24:00:00.000.png
PREFIX_31:25:44.568.png
PREFIX_72:22:16.874.png
The turnside? This should be done via bash (Ubuntu).
Did anyone of you do sth like this? Or does have a solution?
Using any awk:
$ cat tst.sh
#!/usr/bin/env bash
shopt -s extglob
while read -r old new; do
echo mv -- "$old" "$new"
done < <(
printf '%s\n' PREFIX_+([[:digit:]]).png |
awk -F '[_.]' '{
hrs = int( ($2 / (1000 * 60 * 60)) )
mins = int( ($2 / (1000 * 60)) % 60 )
secs = int( ($2 / 1000) % 60 )
ms = $2 % 1000
printf "%s %s_%02d:%02d:%02d.%03d.%s\n", $0, $1, hrs, mins, secs, ms, $3
}'
)
$ ./tst.sh
mv -- PREFIX_10799999.png PREFIX_02:59:59.999.png
mv -- PREFIX_12345678.png PREFIX_03:25:45.678.png
mv -- PREFIX_87654321.png PREFIX_24:20:54.321.png
Remove the echo
once you're happy with the results.
Check the math and tweak if necessary as I mostly just copied it from From milliseconds to hour, minutes, seconds and milliseconds.
Modified to read input from a file and produce the expected output in the question for testing purposes:
$ cat tst.sh
#!/usr/bin/env bash
shopt -s extglob
while read -r old new; do
#echo mv -- "$old" "$new"
echo "$new"
done < <(
# printf '%s\n' PREFIX_+([[:digit:]]).png |
cat file |
awk -F '[_.]' '{
hrs = int( ($2 / (1000 * 60 * 60)) )
mins = int( ($2 / (1000 * 60)) % 60 )
secs = int( ($2 / 1000) % 60 )
ms = $2 % 1000
printf "%s %s_%02d:%02d:%02d.%03d.%s\n", $0, $1, hrs, mins, secs, ms, $3
}'
)
$ ./tst.sh
PREFIX_00:00:00.001.png
PREFIX_00:00:00.001.png
PREFIX_00:00:01.012.png
PREFIX_00:00:01.012.png
PREFIX_00:00:12.106.png
PREFIX_00:00:12.106.png
PREFIX_00:12:05.463.png
PREFIX_00:12:05.463.png
PREFIX_00:20:04.242.png
PREFIX_00:20:04.242.png
PREFIX_02:44:24.336.png
PREFIX_02:44:24.336.png
PREFIX_10:00:12.486.png
PREFIX_10:00:12.486.png
PREFIX_13:41:31.677.png
PREFIX_13:41:31.677.png
PREFIX_24:00:00.000.png
PREFIX_24:00:00.000.png
PREFIX_31:35:44.568.png
PREFIX_72:42:16.874.png