bashshfilenamesdatetime-conversion

How to massconvert filenames from PREFIX_00000000.png to PREFIX_HH:mm:ss.ffff.png


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?


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