Home > Mobile >  Switch the placement of 2 strings in filename, for all files in the folder with bash
Switch the placement of 2 strings in filename, for all files in the folder with bash

Time:11-19

I made a mistake when scraping data, and now my files get allways sorted in the wrong order. Order in the filename now is DD:MM:YYYY but i need it to be MM:DD:YYYY

Examples of the filenames:

07.08.2020-Cf_J-rraZD4.webm      
15.02.2020-KigC0ER_On4.webm      
22.09.2020-m3iAo8SYBko.webm.srt  
30.07.2020-8Qy94fGod_0.webm.srt
07.08.2020-Cf_J-rraZD4.webm.srt  
15.02.2020-KigC0ER_On4.webm.srt  

Is there a simple way to do this with bash?

edit:

i ended up using his:

#! /bin/bash
for f in *.srt ; do
    new=${f:6:4}${f:5:1}${f:3:3}${f:0:3}${f:1:0}${f:11}
    if [[ -f $new ]] ; then
        echo "Can't rename $f: $new already exists!" >&2
    else
        mv "$f" "$new"
    fi
done

CodePudding user response:

Use parameter expansion with the ${var:offset:length} syntax to extract parts of the filenames.

#! /bin/bash
for f in * ; do
    new=${f:3:3}${f:0:2}${f:5}
    if [[ -f $new ]] ; then
        echo "Can't rename $f: $new already exists!" >&2
    else
        mv "$f" "$new"
    fi
done

To just generate the new names, you can process the list of old names with sed:

sed 's/^\(..\)\.\(..\)/\2.\1/'
  • ^ matches the start of a string
  • \(..\) captures two characters, the first such group can be referenced as \1, the second one as \2.
  • \. matches a literal dot.

CodePudding user response:

With Perl's rename of prename command:

rename -n 's/^(..).(..)/$2.$1/' *.webm*

If everything looks fine, remove -n.

CodePudding user response:

You can try this sed

$ sed 's/\([0-9]\{2\}.\)\([0-9]\{2\}.\)\([0-9]\{4\}\)\(.*\)/\2\1\3\4/' input_file
08.07.2020-Cf_J-rraZD4.webm
02.15.2020-KigC0ER_On4.webm
09.22.2020-m3iAo8SYBko.webm.srt
07.30.2020-8Qy94fGod_0.webm.srt
08.07.2020-Cf_J-rraZD4.webm.srt
02.15.2020-KigC0ER_On4.webm.srt

With this code, 4 groups are created and returned with back references. Changing the first and second location will change the timestamp order.

Alternatively, using bash

$ IFS="."; while read -r day month rest; do echo "$month.$day.$rest"; done < input_file
08.07.2020-Cf_J-rraZD4.webm
02.15.2020-KigC0ER_On4.webm
09.22.2020-m3iAo8SYBko.webm.srt
07.30.2020-8Qy94fGod_0.webm.srt
08.07.2020-Cf_J-rraZD4.webm.srt
02.15.2020-KigC0ER_On4.webm.srt

CodePudding user response:

I'm unable to comment on HatLess's post (I think that post incorrectly swapped put the day of the month before the month), but assuming sed is allowed, you can do the following:

#! /bin/bash
for f in * ; do
    new=$(echo $f | sed 's/\([0-9]\{2\}.\)\([0-9]\{2\}\).\([0-9]\{4\}\)\(.*\)/\3.\1\2\4/')
    if [[ -f $new ]] ; then
        echo "Can't rename $f: $new already exists!" >&2
    else
        echo "$f -> $new"
        mv "$f" "$new"
    fi
done

CodePudding user response:

Rename files with GNU sed:

printf "%s\n" *.webm* | sed -E 's/^(..).(..)(.*)/mv & \2.\1\3/e'

CodePudding user response:

endet up using this:

#! /bin/bash
for f in *.srt ; do
    new=${f:6:4}${f:5:1}${f:3:3}${f:0:3}${f:1:0}${f:11}
    if [[ -f $new ]] ; then
        echo "Can't rename $f: $new already exists!" >&2
    else
        mv "$f" "$new"
    fi
done

it does dd.mm.yyyy to yyyy.mm.dd

  • Related